Thread: psql patch (2)

psql patch (2)

From
"Jeroen T. Vermeulen"
Date:
I'm continuing to work on cleaning up code in psql.  As things appear
now, my changes seem to work.  Some possible minor bugs got squished
on the way but I can't be sure without more feedback from people who
really put the code to the test.

The new patch mostly simplifies variable handling and reduces code
duplication.  Changes in the command parser eliminate some redundant
variables (boolean state + depth counter), replaces some
"else if" constructs with switches, and so on.  It is meant to be
applied together with my previous patch, although I hope they don't
conflict; I went back to the CVS version for this one.

One more thing I thought should perhaps be changed: an IGNOREEOF
value of n will ignore only n-1 EOFs.  I didn't want to touch this
for fear of breaking existing applications, but it does seem a tad
illogical.


Jeroen


Attachment

Re: psql patch (2)

From
Bruce Momjian
Date:
Your patch has been added to the PostgreSQL unapplied patches list at:

    http://momjian.postgresql.org/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

---------------------------------------------------------------------------


Jeroen T. Vermeulen wrote:
> I'm continuing to work on cleaning up code in psql.  As things appear
> now, my changes seem to work.  Some possible minor bugs got squished
> on the way but I can't be sure without more feedback from people who
> really put the code to the test.
>
> The new patch mostly simplifies variable handling and reduces code
> duplication.  Changes in the command parser eliminate some redundant
> variables (boolean state + depth counter), replaces some
> "else if" constructs with switches, and so on.  It is meant to be
> applied together with my previous patch, although I hope they don't
> conflict; I went back to the CVS version for this one.
>
> One more thing I thought should perhaps be changed: an IGNOREEOF
> value of n will ignore only n-1 EOFs.  I didn't want to touch this
> for fear of breaking existing applications, but it does seem a tad
> illogical.
>
>
> Jeroen
>

[ Attachment, skipping... ]

>
> ---------------------------(end of broadcast)---------------------------
> TIP 6: Have you searched our list archives?
>
> http://archives.postgresql.org

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: psql patch (2)

From
Bruce Momjian
Date:
Patch applied.  Thanks.

I have attached the patch. I adjusted the cancelConn functions.

I also adjusted this:

    + char parse_char(char **buf)
    + {
    +   long l;
    +
    +   l = strtol(*buf, buf, 0);
    +   (*buf)--;
    +   return (char)l;
    + }
    +

I added the parens around 'buf' because the compiler was saying
statement has no effect.  Is this correct?

---------------------------------------------------------------------------


Jeroen T. Vermeulen wrote:
> I'm continuing to work on cleaning up code in psql.  As things appear
> now, my changes seem to work.  Some possible minor bugs got squished
> on the way but I can't be sure without more feedback from people who
> really put the code to the test.
>
> The new patch mostly simplifies variable handling and reduces code
> duplication.  Changes in the command parser eliminate some redundant
> variables (boolean state + depth counter), replaces some
> "else if" constructs with switches, and so on.  It is meant to be
> applied together with my previous patch, although I hope they don't
> conflict; I went back to the CVS version for this one.
>
> One more thing I thought should perhaps be changed: an IGNOREEOF
> value of n will ignore only n-1 EOFs.  I didn't want to touch this
> for fear of breaking existing applications, but it does seem a tad
> illogical.
>
>
> Jeroen
>

[ Attachment, skipping... ]

>
> ---------------------------(end of broadcast)---------------------------
> TIP 6: Have you searched our list archives?
>
> http://archives.postgresql.org

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/bin/psql/command.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/command.c,v
retrieving revision 1.93
diff -c -c -r1.93 command.c
*** src/bin/psql/command.c    19 Mar 2003 22:49:43 -0000    1.93
--- src/bin/psql/command.c    20 Mar 2003 06:42:19 -0000
***************
*** 669,683 ****
          if (!opt0)
          {
              /* list all variables */
!
!             /*
!              * XXX This is in utter violation of the GetVariable
!              * abstraction, but I have not bothered to do it better.
!              */
!             struct _variable *ptr;
!
!             for (ptr = pset.vars; ptr->next; ptr = ptr->next)
!                 fprintf(stdout, "%s = '%s'\n", ptr->next->name, ptr->next->value);
              success = true;
          }
          else
--- 669,675 ----
          if (!opt0)
          {
              /* list all variables */
!             PrintVariables(pset.vars);
              success = true;
          }
          else
***************
*** 1073,1081 ****
                  save_char = options_string[pos + token_end + 1];
                  options_string[pos + token_end + 1] = '\0';
                  value = GetVariable(pset.vars, options_string + pos + 1);
!                 if (!value)
!                     value = "";
!                 return_val = xstrdup(value);
                  options_string[pos + token_end + 1] = save_char;
                  *string = &options_string[pos + token_end + 1];
                  /* XXX should we set *quote to ':' here? */
--- 1065,1071 ----
                  save_char = options_string[pos + token_end + 1];
                  options_string[pos + token_end + 1] = '\0';
                  value = GetVariable(pset.vars, options_string + pos + 1);
!                 return_val = xstrdup(value ? value : "");
                  options_string[pos + token_end + 1] = save_char;
                  *string = &options_string[pos + token_end + 1];
                  /* XXX should we set *quote to ':' here? */
***************
*** 1287,1301 ****
                  case '7':
                  case '8':
                  case '9':
!                     {
!                         long int    l;
!                         char       *end;
!
!                         l = strtol(p, &end, 0);
!                         c = (char) l;
!                         p = end - 1;
                          break;
!                     }
                  default:
                      c = *p;
              }
--- 1277,1285 ----
                  case '7':
                  case '8':
                  case '9':
!                     c = parse_char((char **)&p);
                          break;
!
                  default:
                      c = *p;
              }
Index: src/bin/psql/common.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/common.c,v
retrieving revision 1.59
diff -c -c -r1.59 common.c
*** src/bin/psql/common.c    20 Mar 2003 06:00:12 -0000    1.59
--- src/bin/psql/common.c    20 Mar 2003 06:42:19 -0000
***************
*** 368,374 ****
  {
      PGresult   *res = NULL;
      PGresult   *newres;
!     const char *var;
      ExecStatusType rstatus;

      if (!pset.db)
--- 368,374 ----
  {
      PGresult   *res = NULL;
      PGresult   *newres;
!     int    echo_hidden;
      ExecStatusType rstatus;

      if (!pset.db)
***************
*** 377,393 ****
          return NULL;
      }

!     var = GetVariable(pset.vars, "ECHO_HIDDEN");
!     if (var)
      {
          printf("********* QUERY **********\n"
                 "%s\n"
                 "**************************\n\n", query);
          fflush(stdout);
-     }

!     if (var && strcmp(var, "noexec") == 0)
          return NULL;

      /* discard any uneaten results of past queries */
      while ((newres = PQgetResult(pset.db)) != NULL)
--- 377,393 ----
          return NULL;
      }

!     echo_hidden = SwitchVariable(pset.vars, "ECHO_HIDDEN", "noexec", NULL);
!     if (echo_hidden != var_notset)
      {
          printf("********* QUERY **********\n"
                 "%s\n"
                 "**************************\n\n", query);
          fflush(stdout);

!         if (echo_hidden == 1)
          return NULL;
+     }

      /* discard any uneaten results of past queries */
      while ((newres = PQgetResult(pset.db)) != NULL)
***************
*** 579,591 ****
      bool OK;

      if (!pset.db)
!             {
          psql_error("You are currently not connected to a database.\n");
          return false;
!             }

      if (GetVariableBool(pset.vars, "SINGLESTEP"))
!             {
          char        buf[3];

          printf(gettext("***(Single step mode: Verify query)*********************************************\n"
--- 579,591 ----
      bool OK;

      if (!pset.db)
!     {
          psql_error("You are currently not connected to a database.\n");
          return false;
!     }

      if (GetVariableBool(pset.vars, "SINGLESTEP"))
!     {
          char        buf[3];

          printf(gettext("***(Single step mode: Verify query)*********************************************\n"
***************
*** 596,609 ****
          if (fgets(buf, sizeof(buf), stdin) != NULL)
              if (buf[0] == 'x')
                  return false;
-             }
-             else
-         {
-         const char *var = GetVariable(pset.vars, "ECHO");
-
-         if (var && strncmp(var, "queries", strlen(var)) == 0)
-             puts(query);
      }

      SetCancelConn();

--- 596,604 ----
          if (fgets(buf, sizeof(buf), stdin) != NULL)
              if (buf[0] == 'x')
                  return false;
      }
+     else if (VariableEquals(pset.vars, "ECHO", "queries"))
+         puts(query);

      SetCancelConn();

***************
*** 619,621 ****
--- 614,628 ----
      PrintNotifications();
      return OK;
  }
+
+
+ char parse_char(char **buf)
+ {
+   long l;
+
+   l = strtol(*buf, buf, 0);
+   (*buf)--;
+   return (char)l;
+ }
+
+
Index: src/bin/psql/common.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/common.h,v
retrieving revision 1.23
diff -c -c -r1.23 common.h
*** src/bin/psql/common.h    20 Mar 2003 06:00:12 -0000    1.23
--- src/bin/psql/common.h    20 Mar 2003 06:42:19 -0000
***************
*** 42,47 ****
--- 42,53 ----
  /* sprompt.h */
  extern char *simple_prompt(const char *prompt, int maxlen, bool echo);

+ /* Parse a numeric character code from the string pointed at by *buf, e.g.
+  * one written as 0x0c (hexadecimal) or 015 (octal); advance *buf to the last
+  * character of the numeric character code.
+  */
+ extern char parse_char(char **buf);
+
  /* Used for all Win32 popen/pclose calls */
  #ifdef WIN32
  #define popen(x,y) _popen(x,y)
Index: src/bin/psql/input.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/input.c,v
retrieving revision 1.22
diff -c -c -r1.22 input.c
*** src/bin/psql/input.c    20 Mar 2003 06:00:12 -0000    1.22
--- src/bin/psql/input.c    20 Mar 2003 06:42:19 -0000
***************
*** 233,242 ****
                                      strlen(PSQLHISTORY) + 1);
              if (psql_history)
              {
!                 const char *var = GetVariable(pset.vars, "HISTSIZE");

-                 if (var)
-                     stifle_history(atoi(var));
                  sprintf(psql_history, "%s/%s", home, PSQLHISTORY);
                  write_history(psql_history);
                  free(psql_history);
--- 233,244 ----
                                      strlen(PSQLHISTORY) + 1);
              if (psql_history)
              {
!                 int hist_size;
!                 hist_size = GetVariableNum(pset.vars,"HISTSIZE",-1,-1,true);
!
!                 if (hist_size >= 0)
!                     stifle_history(hist_size);

                  sprintf(psql_history, "%s/%s", home, PSQLHISTORY);
                  write_history(psql_history);
                  free(psql_history);
Index: src/bin/psql/large_obj.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/large_obj.c,v
retrieving revision 1.23
diff -c -c -r1.23 large_obj.c
*** src/bin/psql/large_obj.c    15 Oct 2002 02:24:16 -0000    1.23
--- src/bin/psql/large_obj.c    20 Mar 2003 06:42:19 -0000
***************
*** 40,54 ****
  static bool
  handle_transaction(void)
  {
-     const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
      PGresult   *res;
!     bool        commit;
      PQnoticeProcessor old_notice_hook;

!     if (var && strcmp(var, "nothing") == 0)
          return true;
!
!     commit = (var && strcmp(var, "commit") == 0);

      notice[0] = '\0';
      old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL);
--- 40,59 ----
  static bool
  handle_transaction(void)
  {
      PGresult   *res;
!     bool        commit = false;
      PQnoticeProcessor old_notice_hook;

!     switch (SwitchVariable(pset.vars, "LO_TRANSACTION",
!                                     "nothing",
!                                     "commit",
!                                     NULL))
!     {
!       case 1:
          return true;
!       case 2:
!          commit = true;
!     }

      notice[0] = '\0';
      old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL);
***************
*** 87,97 ****
  {
      PGresult   *res;
      int            status;
!     bool        own_transaction = true;
!     const char *var = GetVariable(pset.vars, "LO_TRANSACTION");

!     if (var && strcmp(var, "nothing") == 0)
!         own_transaction = false;

      if (!pset.db)
      {
--- 92,100 ----
  {
      PGresult   *res;
      int            status;
!     bool        own_transaction;

!     own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");

      if (!pset.db)
      {
***************
*** 154,164 ****
      Oid            loid;
      char        oidbuf[32];
      unsigned int i;
!     bool        own_transaction = true;
!     const char *var = GetVariable(pset.vars, "LO_TRANSACTION");

!     if (var && strcmp(var, "nothing") == 0)
!         own_transaction = false;

      if (!pset.db)
      {
--- 157,165 ----
      Oid            loid;
      char        oidbuf[32];
      unsigned int i;
!     bool        own_transaction;

!     own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");

      if (!pset.db)
      {
***************
*** 271,281 ****
      int            status;
      Oid            loid = atooid(loid_arg);
      char        buf[256];
-     bool        own_transaction = true;
-     const char *var = GetVariable(pset.vars, "LO_TRANSACTION");

!     if (var && strcmp(var, "nothing") == 0)
!         own_transaction = false;

      if (!pset.db)
      {
--- 272,281 ----
      int            status;
      Oid            loid = atooid(loid_arg);
      char        buf[256];

!     bool        own_transaction;
!
!     own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");

      if (!pset.db)
      {
Index: src/bin/psql/mainloop.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/mainloop.c,v
retrieving revision 1.52
diff -c -c -r1.52 mainloop.c
*** src/bin/psql/mainloop.c    20 Mar 2003 06:00:12 -0000    1.52
--- src/bin/psql/mainloop.c    20 Mar 2003 06:42:25 -0000
***************
*** 40,55 ****
      char       *line;            /* current line of input */
      int            len;            /* length of the line */
      volatile int successResult = EXIT_SUCCESS;
!     volatile backslashResult slashCmdStatus;

      bool        success;
!     volatile char in_quote;        /* == 0 for no in_quote */
!     volatile bool in_xcomment;    /* in extended comment */
!     volatile int xcdepth;
!     volatile int paren_level;
      unsigned int query_start;
      volatile int count_eof = 0;
-     const char *var;
      volatile unsigned int bslash_count = 0;

      int            i,
--- 40,53 ----
      char       *line;            /* current line of input */
      int            len;            /* length of the line */
      volatile int successResult = EXIT_SUCCESS;
!     volatile backslashResult slashCmdStatus = CMD_UNKNOWN;

      bool        success;
!     volatile char in_quote = 0;        /* == 0 for no in_quote */
!     volatile int in_xcomment = 0;    /* in extended comment */
!     volatile int paren_level = 0;
      unsigned int query_start;
      volatile int count_eof = 0;
      volatile unsigned int bslash_count = 0;

      int            i,
***************
*** 81,96 ****
          exit(EXIT_FAILURE);
      }

-     in_xcomment = false;
-     in_quote = 0;
-     paren_level = 0;
-     slashCmdStatus = CMD_UNKNOWN;        /* set default */
      prev_lineno = pset.lineno;
      pset.lineno = 0;


      /* main loop to get queries and execute them */
!     while (1)
      {
          /*
           * Welcome code for Control-C
--- 79,90 ----
          exit(EXIT_FAILURE);
      }

      prev_lineno = pset.lineno;
      pset.lineno = 0;


      /* main loop to get queries and execute them */
!     while (successResult == EXIT_SUCCESS)
      {
          /*
           * Welcome code for Control-C
***************
*** 109,114 ****
--- 103,109 ----
              }

              cancel_pressed = false;
+             fflush(stdout);
          }

  #ifndef WIN32
***************
*** 118,132 ****

              if (pset.cur_cmd_interactive)
              {
!                 fputc('\n', stdout);
                  resetPQExpBuffer(query_buf);

                  /* reset parsing state */
!                 in_xcomment = false;
                  in_quote = 0;
                  paren_level = 0;
                  count_eof = 0;
                  slashCmdStatus = CMD_UNKNOWN;
              }
              else
              {
--- 113,128 ----

              if (pset.cur_cmd_interactive)
              {
!                 putc('\n', stdout);
                  resetPQExpBuffer(query_buf);

                  /* reset parsing state */
!                 in_xcomment = 0;
                  in_quote = 0;
                  paren_level = 0;
                  count_eof = 0;
                  slashCmdStatus = CMD_UNKNOWN;
+                 fflush(stdout);
              }
              else
              {
***************
*** 151,173 ****
              line = xstrdup(query_buf->data);
              resetPQExpBuffer(query_buf);
              /* reset parsing state since we are rescanning whole line */
!             in_xcomment = false;
              in_quote = 0;
              paren_level = 0;
              slashCmdStatus = CMD_UNKNOWN;
          }
-         else
-         {
-             fflush(stdout);
-
              /*
               * otherwise, set interactive prompt if necessary and get
               * another line
               */
!             if (pset.cur_cmd_interactive)
              {
                  int            prompt_status;

                  if (in_quote && in_quote == '\'')
                      prompt_status = PROMPT_SINGLEQUOTE;
                  else if (in_quote && in_quote == '"')
--- 147,167 ----
              line = xstrdup(query_buf->data);
              resetPQExpBuffer(query_buf);
              /* reset parsing state since we are rescanning whole line */
!             in_xcomment = 0;
              in_quote = 0;
              paren_level = 0;
              slashCmdStatus = CMD_UNKNOWN;
          }
              /*
               * otherwise, set interactive prompt if necessary and get
               * another line
               */
!         else if (pset.cur_cmd_interactive)
              {
                  int            prompt_status;

+             fflush(stdout);
+
                  if (in_quote && in_quote == '\'')
                      prompt_status = PROMPT_SINGLEQUOTE;
                  else if (in_quote && in_quote == '"')
***************
*** 185,191 ****
              }
              else
                  line = gets_fromFile(source);
-         }


          /* Setting this will not have effect until next line. */
--- 179,184 ----
***************
*** 203,252 ****
          {
              if (pset.cur_cmd_interactive)
              {
-                 bool        getout = true;
-
                  /* This tries to mimic bash's IGNOREEOF feature. */
!                 const char *val = GetVariable(pset.vars, "IGNOREEOF");
!
!                 if (val)
!                 {
!                     long int    maxeof;
!                     char       *endptr;
!
!                     if (*val == '\0')
!                         maxeof = 10;
!                     else
!                     {
!                         maxeof = strtol(val, &endptr, 0);
!                         if (*endptr != '\0')    /* string not valid as a
!                                                  * number */
!                             maxeof = 10;
!                     }
!
!                     if (count_eof++ != maxeof)
!                         getout = false; /* not quite there yet */
!                 }

!                 if (getout)
!                 {
!                     if (QUIET())
!                         putc('\n', stdout);
!                     else
!                         puts("\\q");
!                     break;
!                 }
!                 else
                  {
                      if (!QUIET())
                          printf(gettext("Use \"\\q\" to leave %s.\n"), pset.progname);
                      continue;
                  }
              }
-             else
- /* not interactive */
                  break;
          }
!         else
              count_eof = 0;

          pset.lineno++;
--- 196,216 ----
          {
              if (pset.cur_cmd_interactive)
              {
                  /* This tries to mimic bash's IGNOREEOF feature. */
!                 count_eof++;

!                 if (count_eof < GetVariableNum(pset.vars,"IGNOREEOF",0,10,false))
                  {
                      if (!QUIET())
                          printf(gettext("Use \"\\q\" to leave %s.\n"), pset.progname);
                      continue;
                  }
+
+                 puts(QUIET() ? "" : "\\q");
              }
                  break;
          }
!
              count_eof = 0;

          pset.lineno++;
***************
*** 259,266 ****
          }

          /* echo back if flag is set */
!         var = GetVariable(pset.vars, "ECHO");
!         if (!pset.cur_cmd_interactive && var && strcmp(var, "all") == 0)
              puts(line);
          fflush(stdout);

--- 223,229 ----
          }

          /* echo back if flag is set */
!         if (!pset.cur_cmd_interactive && VariableEquals(pset.vars, "ECHO", "all"))
              puts(line);
          fflush(stdout);

***************
*** 276,289 ****
  #define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i, pset.encoding))

          success = true;
!         for (i = 0, prevlen = 0, thislen = (len > 0) ? PQmblen(line, pset.encoding) : 0;
!              i < len;
!              ADVANCE_1)
          {
              /* was the previous character a backslash? */
!             bool        was_bslash = (i > 0 && line[i - prevlen] == '\\');
!
!             if (was_bslash)
                  bslash_count++;
              else
                  bslash_count = 0;
--- 239,251 ----
  #define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i, pset.encoding))

          success = true;
!         prevlen = 0;
!         thislen = ((len > 0) ? PQmblen(line, pset.encoding) : 0);
!
!         for (i = 0; (i < len) && (success || !die_on_error); ADVANCE_1)
          {
              /* was the previous character a backslash? */
!             if (i > 0 && line[i - prevlen] == '\\')
                  bslash_count++;
              else
                  bslash_count = 0;
***************
*** 308,337 ****
                      in_quote = 0;
              }

!             /* in extended comment? */
!             else if (in_xcomment)
!             {
!                 if (line[i] == '*' && line[i + thislen] == '/')
!                 {
!                     if (xcdepth > 0)
!                         xcdepth--;
!                     else
                      {
!                         in_xcomment = false;
                          ADVANCE_1;
                      }
-                 }
-                 else if (line[i] == '/' && line[i + thislen] == '*')
-                     xcdepth++;
-             }

!             /* start of extended comment? */
!             else if (line[i] == '/' && line[i + thislen] == '*')
              {
!                 xcdepth = 0;
!                 in_xcomment = true;
                  ADVANCE_1;
              }

              /* start of quote? */
              else if (line[i] == '\'' || line[i] == '"')
--- 270,293 ----
                      in_quote = 0;
              }

!             /* start of extended comment? */
!             else if (line[i] == '/' && line[i + thislen] == '*')
                      {
!                 in_xcomment++;
!                 if (in_xcomment == 1)
                          ADVANCE_1;
                      }

!             /* end of extended comment? */
!             else if (line[i] == '*' && line[i + thislen] == '/')
              {
!                 in_xcomment--;
!                 if (in_xcomment <= 0)
!                 {
!                     in_xcomment = 0;
                  ADVANCE_1;
              }
+             }

              /* start of quote? */
              else if (line[i] == '\'' || line[i] == '"')
***************
*** 353,359 ****

              /* colon -> substitute variable */
              /* we need to be on the watch for the '::' operator */
!             else if (line[i] == ':' && !was_bslash
                    && strspn(line + i + thislen, VALID_VARIABLE_CHARS) > 0
                       && !(prevlen > 0 && line[i - prevlen] == ':')
                  )
--- 309,315 ----

              /* colon -> substitute variable */
              /* we need to be on the watch for the '::' operator */
!             else if (line[i] == ':' && !bslash_count
                    && strspn(line + i + thislen, VALID_VARIABLE_CHARS) > 0
                       && !(prevlen > 0 && line[i - prevlen] == ':')
                  )
***************
*** 411,417 ****
              }

              /* semicolon? then send query */
!             else if (line[i] == ';' && !was_bslash && !paren_level)
              {
                  line[i] = '\0';
                  /* is there anything else on the line? */
--- 367,373 ----
              }

              /* semicolon? then send query */
!             else if (line[i] == ';' && !bslash_count && !paren_level)
              {
                  line[i] = '\0';
                  /* is there anything else on the line? */
***************
*** 442,448 ****
               * if you have a burning need to send a semicolon or colon to
               * the backend ...
               */
!             else if (was_bslash && (line[i] == ';' || line[i] == ':'))
              {
                  /* remove the backslash */
                  memmove(line + i - prevlen, line + i, len - i + 1);
--- 398,404 ----
               * if you have a burning need to send a semicolon or colon to
               * the backend ...
               */
!             else if (bslash_count && (line[i] == ';' || line[i] == ':'))
              {
                  /* remove the backslash */
                  memmove(line + i - prevlen, line + i, len - i + 1);
***************
*** 451,457 ****
              }

              /* backslash command */
!             else if (was_bslash)
              {
                  const char *end_of_cmd = NULL;

--- 407,413 ----
              }

              /* backslash command */
!             else if (bslash_count)
              {
                  const char *end_of_cmd = NULL;

***************
*** 499,513 ****
                      paren_level = 0;

                  /* process anything left after the backslash command */
!                 i += end_of_cmd - &line[i];
                  query_start = i;
              }
-
-
-             /* stop the script after error */
-             if (!success && die_on_error)
-                 break;
-
          }                        /* for (line) */


--- 455,463 ----
                      paren_level = 0;

                  /* process anything left after the backslash command */
!                 i = end_of_cmd - line;
                  query_start = i;
              }
          }                        /* for (line) */


***************
*** 533,557 ****
          if (query_buf->data[0] != '\0' && GetVariableBool(pset.vars, "SINGLELINE"))
          {
              success = SendQuery(query_buf->data);
!             slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
              resetPQExpBuffer(previous_buf);
              appendPQExpBufferStr(previous_buf, query_buf->data);
              resetPQExpBuffer(query_buf);
          }

!
!         if (!success && die_on_error && !pset.cur_cmd_interactive)
          {
              successResult = EXIT_USER;
-             break;
-         }
-
-
          /* Have we lost the db connection? */
!         if (pset.db == NULL && !pset.cur_cmd_interactive)
!         {
              successResult = EXIT_BADCONN;
-             break;
          }
      }                            /* while !endoffile/session */

--- 483,501 ----
          if (query_buf->data[0] != '\0' && GetVariableBool(pset.vars, "SINGLELINE"))
          {
              success = SendQuery(query_buf->data);
!             slashCmdStatus = (success ? CMD_SEND : CMD_ERROR);
              resetPQExpBuffer(previous_buf);
              appendPQExpBufferStr(previous_buf, query_buf->data);
              resetPQExpBuffer(query_buf);
          }

!         if (!pset.cur_cmd_interactive)
          {
+             if (!success && die_on_error)
              successResult = EXIT_USER;
          /* Have we lost the db connection? */
!             else if (!pset.db)
              successResult = EXIT_BADCONN;
          }
      }                            /* while !endoffile/session */

Index: src/bin/psql/prompt.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/prompt.c,v
retrieving revision 1.22
diff -c -c -r1.22 prompt.c
*** src/bin/psql/prompt.c    25 Oct 2001 05:49:54 -0000    1.22
--- src/bin/psql/prompt.c    20 Mar 2003 06:42:26 -0000
***************
*** 69,85 ****
      char        buf[MAX_PROMPT_SIZE + 1];
      bool        esc = false;
      const char *p;
!     const char *prompt_string;

!     if (status == PROMPT_READY)
!         prompt_string = GetVariable(pset.vars, "PROMPT1");
!     else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status ==
PROMPT_COMMENT|| status == PROMPT_PAREN) 
!         prompt_string = GetVariable(pset.vars, "PROMPT2");
!     else if (status == PROMPT_COPY)
!         prompt_string = GetVariable(pset.vars, "PROMPT3");
!     else
!         prompt_string = "? ";


      destination[0] = '\0';

--- 69,98 ----
      char        buf[MAX_PROMPT_SIZE + 1];
      bool        esc = false;
      const char *p;
!     const char *prompt_string = "? ";
!     const char *prompt_name = NULL;

!     switch (status)
!     {
!         case PROMPT_READY:
!             prompt_name = "PROMPT1";
!             break;
!
!         case PROMPT_CONTINUE:
!         case PROMPT_SINGLEQUOTE:
!         case PROMPT_DOUBLEQUOTE:
!         case PROMPT_COMMENT:
!         case PROMPT_PAREN:
!             prompt_name = "PROMPT2";
!             break;
!
!         case PROMPT_COPY:
!             prompt_name = "PROMPT3";
!             break;
!     }

+     if (prompt_name)
+       prompt_string = GetVariable(pset.vars, prompt_name);

      destination[0] = '\0';

***************
*** 92,112 ****
          {
              switch (*p)
              {
-                 case '%':
-                     strcpy(buf, "%");
-                     break;
-
                      /* Current database */
                  case '/':
                      if (pset.db)
                          strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
                      break;
                  case '~':
-                     {
-                         const char *var;
-
                          if (pset.db)
                          {
                              if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
                                  ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
                                  strcpy(buf, "~");
--- 105,119 ----
          {
              switch (*p)
              {
                      /* Current database */
                  case '/':
                      if (pset.db)
                          strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
                      break;
                  case '~':
                          if (pset.db)
                          {
+                         const char *var;
                              if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
                                  ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
                                  strcpy(buf, "~");
***************
*** 114,120 ****
                                  strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
                          }
                          break;
!                     }
                      /* DB server hostname (long/short) */
                  case 'M':
                  case 'm':
--- 121,127 ----
                                  strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
                          }
                          break;
!
                      /* DB server hostname (long/short) */
                  case 'M':
                  case 'm':
***************
*** 164,178 ****
                  case '7':
                  case '8':
                  case '9':
!                     {
!                         long int    l;
!                         char       *end;
!
!                         l = strtol(p, &end, 0);
!                         sprintf(buf, "%c", (unsigned char) l);
!                         p = end - 1;
                          break;
-                     }

                  case 'R':
                      switch (status)
--- 171,178 ----
                  case '7':
                  case '8':
                  case '9':
!                     *buf = parse_char(&p);
                          break;

                  case 'R':
                      switch (status)
Index: src/bin/psql/startup.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/startup.c,v
retrieving revision 1.71
diff -c -c -r1.71 startup.c
*** src/bin/psql/startup.c    18 Mar 2003 22:15:44 -0000    1.71
--- src/bin/psql/startup.c    20 Mar 2003 06:42:26 -0000
***************
*** 253,262 ****
       */
      else if (options.action == ACT_SINGLE_SLASH)
      {
!         const char *value;
!
!         if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0)
              puts(options.action_string);
          successResult = HandleSlashCmds(options.action_string, NULL, NULL, NULL) != CMD_ERROR
              ? EXIT_SUCCESS : EXIT_FAILURE;
      }
--- 253,261 ----
       */
      else if (options.action == ACT_SINGLE_SLASH)
      {
!         if (VariableEquals(pset.vars, "ECHO", "all"))
              puts(options.action_string);
+
          successResult = HandleSlashCmds(options.action_string, NULL, NULL, NULL) != CMD_ERROR
              ? EXIT_SUCCESS : EXIT_FAILURE;
      }
***************
*** 266,275 ****
       */
      else if (options.action == ACT_SINGLE_QUERY)
      {
!         const char *value;
!
!         if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0)
              puts(options.action_string);
          successResult = SendQuery(options.action_string)
              ? EXIT_SUCCESS : EXIT_FAILURE;
      }
--- 265,273 ----
       */
      else if (options.action == ACT_SINGLE_QUERY)
      {
!         if (VariableEquals(pset.vars, "ECHO", "all"))
              puts(options.action_string);
+
          successResult = SendQuery(options.action_string)
              ? EXIT_SUCCESS : EXIT_FAILURE;
      }
Index: src/bin/psql/variables.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/variables.c,v
retrieving revision 1.9
diff -c -c -r1.9 variables.c
*** src/bin/psql/variables.c    10 Feb 2001 02:31:28 -0000    1.9
--- src/bin/psql/variables.c    20 Mar 2003 06:42:26 -0000
***************
*** 68,73 ****
--- 68,141 ----
  }


+ bool
+ VariableEquals(VariableSpace space, const char name[], const char value[])
+ {
+     const char *var;
+     var = GetVariable(space, name);
+     return var && (strcmp(var, value) == 0);
+ }
+
+
+ int
+ GetVariableNum(VariableSpace space,
+                      const char name[],
+                     int defaultval,
+                     int faultval,
+                     bool allowtrail)
+ {
+     const char *var;
+     int result;
+
+     var = GetVariable(space, name);
+     if (!var)
+       result = defaultval;
+     else if (!var[0])
+       result = faultval;
+     else
+     {
+         char *end;
+         result = strtol(var, &end, 0);
+         if (!allowtrail && *end)
+           result = faultval;
+     }
+
+     return result;
+ }
+
+
+ int
+ SwitchVariable(VariableSpace space, const char name[], const char *opt, ...)
+ {
+     int result;
+     const char *var;
+
+     var = GetVariable(space, name);
+     if (var)
+     {
+         va_list args;
+         va_start(args, opt);
+         for (result=1; opt && (strcmp(var, opt) != 0); result++)
+             opt = va_arg(args,const char *);
+
+         if (!opt) result = var_notfound;
+         va_end(args);
+     }
+     else
+       result = var_notset;
+
+     return result;
+ }
+
+
+ void
+ PrintVariables(VariableSpace space)
+ {
+   struct _variable *ptr;
+   for (ptr = space->next; ptr; ptr = ptr->next)
+      printf("%s = '%s'\n", ptr->name, ptr->value);
+ }
+

  bool
  SetVariable(VariableSpace space, const char *name, const char *value)
Index: src/bin/psql/variables.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/variables.h,v
retrieving revision 1.10
diff -c -c -r1.10 variables.h
*** src/bin/psql/variables.h    5 Nov 2001 17:46:31 -0000    1.10
--- src/bin/psql/variables.h    20 Mar 2003 06:42:26 -0000
***************
*** 30,39 ****

  VariableSpace CreateVariableSpace(void);
  const char *GetVariable(VariableSpace space, const char *name);
! bool        GetVariableBool(VariableSpace space, const char *name);
! bool        SetVariable(VariableSpace space, const char *name, const char *value);
! bool        SetVariableBool(VariableSpace space, const char *name);
! bool        DeleteVariable(VariableSpace space, const char *name);
! void        DestroyVariableSpace(VariableSpace space);

  #endif   /* VARIABLES_H */
--- 30,62 ----

  VariableSpace CreateVariableSpace(void);
  const char *GetVariable(VariableSpace space, const char *name);
! bool    GetVariableBool(VariableSpace space, const char *name);
! bool    VariableEquals(VariableSpace space, const char name[], const char *opt);
!
! /* Read numeric variable, or defaultval if it is not set, or faultval if its
!  * value is not a valid numeric string.  If allowtrail is false, this will
!  * include the case where there are trailing characters after the number.
!  */
! int GetVariableNum(VariableSpace space,
!                          const char name[],
!                         int defaultval,
!                         int faultval,
!                         bool allowtrail);
!
!
! /* Find value of variable <name> among NULL-terminated list of alternative
!  * options.  Returns var_notset if the variable was not set, var_notfound if its
!  * value did not occur in the list of options, or the number of the matching
!  * option.  The first option is 1, the second is 2 and so on.
!  */
! enum { var_notset = 0, var_notfound = -1 };
! int     SwitchVariable(VariableSpace space, const char name[], const char *opt,...);
!
! void     PrintVariables(VariableSpace space);
!
! bool    SetVariable(VariableSpace space, const char *name, const char *value);
! bool    SetVariableBool(VariableSpace space, const char *name);
! bool    DeleteVariable(VariableSpace space, const char *name);
! void    DestroyVariableSpace(VariableSpace space);

  #endif   /* VARIABLES_H */

Re: psql patch (2)

From
Bruce Momjian
Date:
OK, fixed as you suggested.

---------------------------------------------------------------------------

Jeroen T. Vermeulen wrote:
> On Thu, Mar 20, 2003 at 01:45:31AM -0500, Bruce Momjian wrote:
> >
> > I also adjusted this:
> >
> >     + char parse_char(char **buf)
> >     + {
> >     +   long l;
> >     +
> >     +   l = strtol(*buf, buf, 0);
> >     +   (*buf)--;
> >     +   return (char)l;
> >     + }
> >     +
> >
> > I added the parens around 'buf' because the compiler was saying
> > statement has no effect.  Is this correct?
>
> I don't remember what this function does, but you could also write
> '--*buf;' to save on parentheses (and do your bit for the environment).
>
>
> Jeroen
>
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: psql patch (2)

From
"Jeroen T. Vermeulen"
Date:
On Thu, Mar 20, 2003 at 01:45:31AM -0500, Bruce Momjian wrote:
>
> I also adjusted this:
>
>     + char parse_char(char **buf)
>     + {
>     +   long l;
>     +
>     +   l = strtol(*buf, buf, 0);
>     +   (*buf)--;
>     +   return (char)l;
>     + }
>     +
>
> I added the parens around 'buf' because the compiler was saying
> statement has no effect.  Is this correct?

I don't remember what this function does, but you could also write
'--*buf;' to save on parentheses (and do your bit for the environment).


Jeroen