Fixed psql double quoting of SQL ids
authorPeter Eisentraut
Mon, 7 Feb 2000 23:10:11 +0000 (23:10 +0000)
committerPeter Eisentraut
Mon, 7 Feb 2000 23:10:11 +0000 (23:10 +0000)
Fixed libpq printing functions

29 files changed:
doc/src/sgml/libpq.sgml
doc/src/sgml/ref/psql-ref.sgml
src/bin/psql/command.c
src/bin/psql/common.c
src/bin/psql/create_help.pl
src/bin/psql/describe.c
src/bin/psql/help.c
src/bin/psql/input.c
src/bin/psql/input.h
src/bin/psql/large_obj.c
src/bin/psql/mainloop.c
src/bin/psql/print.c
src/bin/psql/prompt.c
src/bin/psql/prompt.h
src/bin/psql/startup.c
src/bin/psql/stringutils.c
src/bin/psql/stringutils.h
src/bin/psql/tab-complete.c
src/interfaces/libpq/fe-auth.c
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/fe-exec.c
src/interfaces/libpq/fe-lobj.c
src/interfaces/libpq/fe-misc.c
src/interfaces/libpq/fe-print.c
src/interfaces/libpq/libpq-fe.h
src/interfaces/libpq/libpq-int.h
src/interfaces/libpq/pqexpbuffer.c
src/interfaces/libpq/pqexpbuffer.h
src/interfaces/libpq/win32.h

index 46e90bbe88c5a4f650f8631d1e6b7a652eb48ea7..964dde8054bc7361d634ec40dfcdc17d62efebcc 100644 (file)
@@ -494,7 +494,7 @@ soon.)
 PQdb  
          Returns the database name of the connection.
 
-const char *PQdb(const PGconn *conn)
+char *PQdb(const PGconn *conn)
 
 PQdb and the next several functions return the values established
 at connection.  These values are fixed for the life of the PGconn
@@ -507,7 +507,7 @@ object.
 PQuser
          Returns the user name of the connection.
 
-const char *PQuser(const PGconn *conn)
+char *PQuser(const PGconn *conn)
 
 
 
@@ -517,7 +517,7 @@ const char *PQuser(const PGconn *conn)
 PQpass
          Returns the password of the connection.
 
-const char *PQpass(const PGconn *conn)
+char *PQpass(const PGconn *conn)
 
 
 
@@ -527,7 +527,7 @@ const char *PQpass(const PGconn *conn)
 PQhost
          Returns the server host name of the connection.
 
-const char *PQhost(const PGconn *conn)
+char *PQhost(const PGconn *conn)
 
 
 
@@ -537,7 +537,7 @@ const char *PQhost(const PGconn *conn)
 PQport
          Returns the port of the connection.
 
-const char *PQport(const PGconn *conn)
+char *PQport(const PGconn *conn)
 
 
 
@@ -547,7 +547,7 @@ const char *PQport(const PGconn *conn)
 PQtty
          Returns the debug tty of the connection.
 
-const char *PQtty(const PGconn *conn)
+char *PQtty(const PGconn *conn)
 
 
 
@@ -557,7 +557,7 @@ const char *PQtty(const PGconn *conn)
 PQoptions
        Returns the backend options used in  the  connection.
 
-const char *PQoptions(const PGconn *conn)
+char *PQoptions(const PGconn *conn)
 
 
 
@@ -602,7 +602,7 @@ ConnStatusType PQstatus(const PGconn *conn)
        Returns the error message most recently generated by
        an operation on the connection.
        
-const char *PQerrorMessage(const PGconn* conn);
+char *PQerrorMessage(const PGconn* conn);
        
       
 
@@ -790,7 +790,7 @@ exposes a bug in the client software.
    Converts the enumerated type returned by PQresultStatus into
    a string constant describing the status code.
 
-const char *PQresStatus(ExecStatusType status);
+char *PQresStatus(ExecStatusType status);
 
 
 
@@ -801,7 +801,7 @@ const char *PQresStatus(ExecStatusType status);
 returns the error message associated with the query, or an empty string
 if there was no error.
 
-const char *PQresultErrorMessage(const PGresult *res);
+char *PQresultErrorMessage(const PGresult *res);
 
 Immediately following a PQexec or PQgetResult
 call, PQerrorMessage (on the connection) will return the same
@@ -855,7 +855,7 @@ extracts data from a BINARY cursor.
  Returns the field (attribute) name associated with the given field  index.
  Field  indices start at 0.
 
-const char *PQfname(const PGresult *res,
+char *PQfname(const PGresult *res,
                     int field_index);
 
 
@@ -931,9 +931,9 @@ int PQfmod(const PGresult *res,
        of a PGresult.
        Tuple and field indices start at 0.
 
-const char* PQgetvalue(const PGresult *res,
-                       int tup_num,
-                       int field_num);
+char* PQgetvalue(const PGresult *res,
+                 int tup_num,
+                 int field_num);
 
 For most queries, the value returned by PQgetvalue
 is a null-terminated ASCII string  representation
@@ -991,7 +991,7 @@ int PQgetisnull(const PGresult *res,
           Returns the command status string from the SQL command that
      generated the PGresult.
 
-const char * PQcmdStatus(const PGresult *res);
+char * PQcmdStatus(const PGresult *res);
 
 
 
@@ -1001,7 +1001,7 @@ const char * PQcmdStatus(const PGresult *res);
 PQcmdTuples
      Returns the number of rows affected by the SQL command.
 
-const char * PQcmdTuples(const PGresult *res);
+char * PQcmdTuples(const PGresult *res);
 
           If the SQL command that generated the
      PGresult was INSERT, UPDATE or DELETE, this returns a
@@ -1032,7 +1032,7 @@ Oid PQoidValue(const PGresult *res);
           inserted,  if  the SQL command was an INSERT.
           Otherwise, returns an empty string.
 
-const char * PQoidStatus(const PGresult *res);
+char * PQoidStatus(const PGresult *res);
 
 The function is deprecated in favor of PQoidValue
 and is not thread-safe.
@@ -1050,25 +1050,25 @@ void PQprint(FILE* fout,      /* output stream */
              const PQprintOpt *po);
 
 struct {
-    int     header;      /* print output field headings and row count */
-    int     align;       /* fill align the fields */
-    int     standard;    /* old brain dead format */
-    int     html3;       /* output html tables */
-    int     expanded;    /* expand tables */
-    int     pager;       /* use pager for output if needed */
+    pqbool  header;      /* print output field headings and row count */
+    pqbool  align;       /* fill align the fields */
+    pqbool  standard;    /* old brain dead format */
+    pqbool  html3;       /* output html tables */
+    pqbool  expanded;    /* expand tables */
+    pqbool  pager;       /* use pager for output if needed */
     char    *fieldSep;   /* field separator */
     char    *tableOpt;   /* insert to HTML <table ...> */
     char    *caption;    /* HTML <caption> */
     char    **fieldName; /* null terminated array of replacement field names */
 } PQprintOpt;
 
-
 This function was formerly used by psql
 to print query results, but this is no longer the case and this
-function is no longer supported.
+function is no longer actively supported.
 
 
 
+
 
 
 PQclear
index 8f68d7ede4959be4cadfe43599d890e4a292b006..4d0bf428c0a8e3665fae43f78186fcb16dad5dc9 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -64,8 +64,8 @@ Postgres documentation
 
     
     psql is a regular PostgreSQL
-    client application. In order to connect to a database you need to determine
-    name of you target database, the hostname and port number of the server
+    client application. In order to connect to a database you need to know the
+    name of your target database, the hostname and port number of the server
     and what user name you want to connect as. psql can be
     told about those parameters via command line options, namely ,
     , and  respectively.
@@ -119,7 +119,7 @@ testdb=>
     Ordinarily, input lines are sent to the backend when a query-terminating
     semicolon is reached. An end of line does not terminate a query! Thus queries
     can be spread over serveral lines for clarity. If the query was sent and without
-    error the query results are displayed on the screen.
+    error, the query results are displayed on the screen.
     
 
     
@@ -155,31 +155,35 @@ testdb=>
     
 
     
-    To include whitespace into an argument you must quote it with either single
-    or double quotes. Anything contained in single quotes (except for a
-    backslash-escaped single quote itself) is taken literally as the argument.
-    Anything contained in double quotes is furthermore subject to C-like
-    substitutions for \n (new line), \t (tab),
-    \digits,
+    To include whitespace into an argument you must quote it with a single
+    quote. To include a single quote into such an argument, preceed it by
+    a backslash. Anything contained in single quotes is furthermore subject to
+    C-like substitutions for \n (new line), \t
+     (tab), \digits,
     \0digits, and
     \0xdigits
     (the character with the given decimal, octal, or hexadecimal code).
     
 
     
-    If an unquoted argument begins with a dollar sign ($),
+    If an unquoted argument begins with a colon (:),
     it is taken as a variable and the value of the variable is taken as the
-    argument instead. Inside double quotes, variable values can be substituted
-    by enclosing the name in a ${...} sequence. See also under
-    .
+    argument instead.
     
 
     
-    Arguments that are quoted in back-ticks (`)
-    are taken as a command line
-    that is passed to the shell. The output of the command (with a trailing
-    newline removed) is taken as the argument value. Back-ticks are subject to
-    the same substitution rules as double-quotes.
+    Arguments that are quoted in backticks (`)
+    are taken as a command line that is passed to the shell. The output of the
+    command (with a trailing newline removed) is taken as the argument value.
+    The above escape sequences also apply in backticks.
+    
+
+    
+    Some commands take the name of an SQL identifier (such as
+    a table name) as argument. These arguments follow the syntax rules of
+    SQL regarding double quotes: an identifier without
+    double quotes is coerced to lower-case. For all other commands
+    double quotes are not special and will become part of the argument.
     
 
     
@@ -189,7 +193,7 @@ testdb=>
     (two backslashes) marks the end of arguments and continues parsing
     SQL queries, if any. That way SQL and
     psql commands can be freely mixed on a line.
-    In any case, the arguments of a meta-command cannot continue beyond the end
+    But in any case, the arguments of a meta-command cannot continue beyond the end
     of the line. 
     
 
@@ -246,7 +250,7 @@ testdb=>
 
    
    If the connection attempt failed (wrong username, access denied, etc.) the
-   previous connection will be kept, if and only if psql is
+   previous connection will be kept if and only if psql is
    in interactive mode. When executing a non-interactive script, processing
    will immediately stop with an error. This distinction was chosen as a user
    convenience against typos on the one hand, and a safety mechanism that
@@ -286,7 +290,7 @@ testdb=>
         
    This operation is not as efficient as the SQL 
    COPY command because all data must pass through the
-   client/server IP or socket connection. For large amounts of data this other
+   client/server IP or socket connection. For large amounts of data the other
    technique may be preferable.
         
         
@@ -510,12 +514,15 @@ testdb=>
         \echo text [ ... ]
         
    
-        Prints the arguments to the standard output. This can be useful to
+        Prints the arguments to the standard output, separated by one space and
+        followed by a newline. This can be useful to
         intersperse information in the output of scripts. For example:
 
 => \echo `date`
 Tue Oct 26 21:40:57 CEST 1999
 
+        If the first argument is an unquoted -n the the trailing
+        newline is not written.
    
 
    
@@ -602,7 +609,7 @@ Tue Oct 26 21:40:57 CEST 1999
    
    
    If you want to see the lines on the screen as they are read you must set
-   the variable echo>.
+   the variable ECHO to full>.
    
    
         
@@ -658,7 +665,7 @@ Tue Oct 26 21:40:57 CEST 1999
    Stores the file into a PostgreSQL large object.
    Optionally, it associates the given comment with the object. Example:
 
-foo=> \lo_import '/home/me/pictures/photo.xcf' 'a picture of me'
+foo=> \lo_import '/home/peter/pictures/photo.xcf' 'a picture of me'
 lo_import 152801
 
    The response indicates that the large object received object id 152801
@@ -1006,12 +1013,13 @@ lo_import 152801
 
 
       
-        \set [ name [ value ]]
+        \set [ name [ value [ ... ]]]
 
    
    
    Sets the internal variable name
-   to value. If no second argument
+   to value or, if more than one
+        value is given, to the concatenation of all of them. If no second argument
    is given, the variable is just set with not value. To unset a variable, use
         the \unset command.
    
@@ -1145,9 +1153,7 @@ Access permissions for database "test"
         
         Escapes to a separate Unix shell or executes the Unix command
         command. The arguments
-        are not further interpreted, the shell will see them as is. If you wish
-        to capture the output of a shell command and/or use psql's
-        variable substitution features, use the backticks (`).
+        are not further interpreted, the shell will see them as is.
         
         
       
@@ -1200,7 +1206,7 @@ Access permissions for database "test"
       
       Specifies that psql
       is to execute one query string, query,
-      and then exit.  This is useful for shell scripts.
+      and then exit.  This is useful in shell scripts.
       
       
       query must be either a query string
@@ -1208,8 +1214,8 @@ Access permissions for database "test"
       specific features), or it is a single backslash command. Thus
       you cannot mix SQL and psql
       meta-commands. To achieve this you could pipe the string into
-      psql and finish it with a a \q,
-      like so: echo "select * from foo; \q" | psql.
+      psql, like so:
+      echo "\x \\ select * from foo;" | psql.
       
       
     
@@ -1260,6 +1266,16 @@ Access permissions for database "test"
       After the file is processed, psql terminates.
       This in many ways equivalent to the internal command \i.
       
+      
+      Using this option is subtly different from writing
+      psql < filename.
+      In general, both will do what you expect, but using -f
+      enables some nice features such as error messages with line numbers.
+      There is also a slight chance that using this option will reduce
+      the startup overhead. On the other hand, the variant using the shell's
+      input redirection is (in theory) guaranteed to yield exactly the same
+      output that you would have gotten had you entered everything by hand.
+      
       
     
 
@@ -1311,16 +1327,6 @@ Access permissions for database "test"
     
 
 
-    
-      -n, --no-readline
-      
-      
-      Do not use readline for line editing and do not use the history.
-      
-      
-    
-
-
     
       -o, --output filename
       
@@ -1372,6 +1378,17 @@ Access permissions for database "test"
       
     
 
+
+    
+      -R, --record-separator separator
+      
+      
+      Use separator as the record separator.
+      This is equivalent to the \pset recordsep command.
+      
+      
+    
+
  
     
       -s, --single-step
@@ -1492,7 +1509,7 @@ Access permissions for database "test"
       
       As of version 7.0, psql automatically issues a
       password prompt whenever the backend requests password authentication.
-      Because this is currently based on a hack the automatic
+      Because this is currently based on a hack, the automatic
       recognition might mysteriously fail, hence this option to force a prompt.
       If no password prompt is issued and the backend requires password authentication
       the connection attempt will fail.
@@ -1539,46 +1556,39 @@ Access permissions for database "test"
 
     
     psql provides variable substitution features
-    similar to common Unix command shells. Variables are simply name/value
+    similar to common Unix command shells. This feature is new and not very
+    sophisticated, yet, but there are plans to expand it in the future.
+    Variables are simply name/value
     pairs, where the value can be any string of any length. To set variables,
     use the psql meta-command \set:
 
 testdb=> \set foo bar
 
     sets the variable foo to the value bar. To retrieve
-    the content of the variable, precede the name with a dollar-sign and use it
+    the content of the variable, precede the name with a colon and use it
     as the argument of any slash command:
 
-testdb=> \echo $foo
+testdb=> \echo :foo
 bar
 
-    Alternatively, the value can also be interpolated into a double-quoted (or backtick-quoted)
-    string, like so:
-
-testdb=> \echo "foo is now ${foo}."
-foo is now bar.
-
-    (The curly braces are required.) No variable substitution
-    will be performed in single-quoted strings or in any of the backslash commands
-    that have special parsing rules (e.g., \copy).
     
 
     
     
     The arguments of \set are subject to the same substitution
     rules as with other commands. Thus you can construct interesting references
-    such as \set "${foo}bar" 'something' and get soft
+    such as \set :foo 'something' and get soft
     links or variable variables of Perl
     or PHP fame, respectively.
     Unfortunately (or fortunately?), there is not way to do anything useful
-    with these constructs. (\echo ${${foo}} doesn't work.) On the
-    other hand, \set bar $foo is a perfectly valid way to copy
+    with these constructs. On the
+    other hand, \set bar :foo is a perfectly valid way to copy
     a variable.
     
     
 
     
-    If you call \set without an argument, the variable is simply
+    If you call \set without a second argument, the variable is simply
     set, but has no value. To unset (or delete) a variable, use the command
     \unset.
     
@@ -1830,7 +1840,7 @@ foo is now bar.
     
     An additional useful feature of psql variables
     is that you can substitute (interpolate) them into
-    regular SQL statements. The syntax for this is to prepend
+    regular SQL statements. The syntax for this is again to prepend
     the variable name with a colon (:).
 
 testdb=> \set foo 'my_table'
@@ -1850,8 +1860,7 @@ testdb=> SELECT * FROM :foo;
     Another possible use of this mechanism is to copy the contents of a file
     into a field. First load the file into a variable and then proceed as above.
 
-testdb=> \set content `cat my_file.txt`
-testdb=> \set content "'${content}'"
+testdb=> \set content '\'' `cat my_file.txt` '\''
 testdb=> INSERT INTO my_table VALUES (:content);
 
     One possible problem with this approach is that my_file.txt
@@ -1877,11 +1886,12 @@ testdb=> \set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`
 
     
     Since colons may legally appear in queries, the following rule applies: If the variable
-    is not set, the character sequence colon-name is not changed. In any
+    is not set, the character sequence colon name is not changed. In any
     case you can escape a colon with a backslash to protect it from interpretation.
     (The colon syntax for variables is standard SQL for embedded
     query languages, such as ecpg. The colon syntax for
-    array slices and type casts are PostgreSQL extensions.)
+    array slices and type casts are PostgreSQL extensions,
+    hence the conflict.)
     
 
   
@@ -1975,7 +1985,7 @@ testdb=> \set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`
       
 
       
-        %$name$
+        %:name:
    
    The value of the psqlmagic, or environment
    variable name. See the section
@@ -2032,13 +2042,22 @@ testdb=> \set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`
 
     
     psql supports the readline and history libraries for
-    convenienent line editing and retrieval. The command history is stored in a file
+    convenient line editing and retrieval. The command history is stored in a file
     named .psql_history in your home directory and is reloaded when
     psql starts up.
     Tab-completion is also supported, although
     the completion logic makes no claim to be an SQL parser.
     When available, psql is automatically built to use these
-    features.
+    features. If for some reason you do not like the tab completion, you can turn if off
+    by putting this in a file named .inputrc in your
+    home directory:
+
+$if psql
+set disable-completion on
+$endif
+
+    (This is not a psql but a readline
+    feature. Read its documentation for further details.)
     
 
     
@@ -2053,7 +2072,7 @@ testdb=> \set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`
     you have the library and header files installed in an obscure place you
     must tell configure about them, for example:
 
-$ ./configure --with-includes=/opt/gnu/include --with-libraries=/opt/gnu/lib  ...
+$ ./configure --with-includes=/opt/gnu/include --with-libs=/opt/gnu/lib  ...
 
     Then you have to recompile psql (not necessarily
     the entire code tree).
@@ -2105,7 +2124,7 @@ testdb=> \d my_table
   At this point you decide to change the prompt to something more
   interesting:
 
-testdb=> \set prompt1 '%n@%m %~%R%# '
+testdb=> \set PROMPT1 '%n@%m %~%R%# '
 peter@localhost testdb=>
 
   Let's assume you have filled the table with data and want to take a look at it:
@@ -2221,14 +2240,6 @@ Field separator is "oo".
       
       
 
-      
-      
-      The number of options for a backslash command is limited, probably to 16.
-      You can easily change this in the source code, and perhaps I will get around
-      to fixing this one day. Not that there is any command
-      that actually uses that many options though.
-      
-      
     
 
   
index 63ac6fbff424b742f9c48c1ee43e415f6fc0b43a..ba198d7d914665d3f5297bbb9c05e190231df9e8 100644 (file)
@@ -3,12 +3,13 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.17 2000/02/05 12:27:56 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.18 2000/02/07 23:10:04 petere Exp $
  */
 #include 
 #include "command.h"
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include          /* for umask() */
 #include           /* for umask(), stat() */
 #include                 /* for geteuid(), getpid(), stat() */
+#else
+#include 
 #endif
-#include 
 
 #include 
 #include 
 
-#include "stringutils.h"
-#include "mainloop.h"
+#include "common.h"
 #include "copy.h"
+#include "describe.h"
 #include "help.h"
-#include "settings.h"
-#include "common.h"
+#include "input.h"
 #include "large_obj.h"
+#include "mainloop.h"
 #include "print.h"
-#include "describe.h"
-#include "input.h"
+#include "settings.h"
 #include "variables.h"
 
-#ifdef WIN32
-#include "../../interfaces/libpq/win32.h"
-#define popen(x,y) _popen(x,y)
-#define pclose(x) _pclose(x)
-#endif
-
 
 /* functions for use in this file */
 
 static backslashResult exec_command(const char *cmd,
-            char *const * options,
             const char *options_string,
+             const char ** continue_parse,
             PQExpBuffer query_buf);
 
-static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
-
-static char * unescape(const char *source);
-
-static bool do_connect(const char *new_dbname,
-                       const char *new_user);
-
+enum option_type { OT_NORMAL, OT_SQLID };
+static char * scan_option(char ** string, enum option_type type, char * quote);
+static char * unescape(const unsigned char *source, size_t len);
 
+static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
+static bool do_connect(const char *new_dbname, const char *new_user);
 static bool do_shell(const char *command);
 
-/*
- * Perhaps this should be changed to "infinity",
- * but there is no convincing reason to bother
- * at this point.
- */
-#define NR_OPTIONS 16
 
 
 /*----------
@@ -79,7 +66,7 @@ static bool do_shell(const char *command);
  *
  * 'query_buf' contains the query-so-far, which may be modified by
  * execution of the backslash command (for example, \r clears it)
- * query_buf can be NULL if there is no query-so-far.
+ * query_buf can be NULL if there is no query so far.
  *
  * Returns a status code indicating what action is desired, see command.h.
  *----------
@@ -92,18 +79,13 @@ HandleSlashCmds(const char *line,
 {
    backslashResult status = CMD_SKIP_LINE;
    char       *my_line;
-   char       *options[NR_OPTIONS+1];
-   char       *token;
-   const char *options_string = NULL;
-   const char *cmd;
+   char       *options_string = NULL;
    size_t      blank_loc;
-   int         i;
    const char *continue_parse = NULL;  /* tell the mainloop where the
                                         * backslash command ended */
 
 #ifdef USE_ASSERT_CHECKING
     assert(line);
-    assert(query_buf);
     assert(end_of_cmd);
 #endif
 
@@ -129,145 +111,37 @@ HandleSlashCmds(const char *line,
        my_line[blank_loc] = '\0';
    }
 
-    options[0] = NULL;
-
-   if (options_string)
-   {
-       char        quote;
-       unsigned int pos;
-
-       options_string = &options_string[strspn(options_string, " \t")];        /* skip leading
-                                                                                * whitespace */
-
-       i = 0;
-       token = strtokx(options_string, " \t", "\"'`", '\\', "e, &pos, pset.encoding);
-
-       for (i = 0; token && i < NR_OPTIONS; i++)
-       {
-           switch (quote)
-           {
-               case '"':
-                   options[i] = unescape(token);
-                   break;
-               case '\'':
-                   options[i] = xstrdup(token);
-                   break;
-               case '`':
-                   {
-                       bool        error = false;
-                       FILE       *fd = NULL;
-                       char       *file = unescape(token);
-                       PQExpBufferData output;
-                       char        buf[512];
-                       size_t      result;
-
-                       fd = popen(file, "r");
-                       if (!fd)
-                       {
-                            psql_error("%s: %s\n", file, strerror(errno));
-                           error = true;
-                       }
-
-                       if (!error)
-                       {
-                           initPQExpBuffer(&output);
-
-                           do
-                           {
-                               result = fread(buf, 1, 512, fd);
-                               if (ferror(fd))
-                               {
-                                    psql_error("%s: %s\n", file, strerror(errno));
-                                   error = true;
-                                   break;
-                               }
-                               appendBinaryPQExpBuffer(&output, buf, result);
-                           } while (!feof(fd));
-                           appendPQExpBufferChar(&output, '\0');
-
-                           if (pclose(fd) == -1)
-                           {
-                                psql_error("%s: %s\n", file, strerror(errno));
-                               error = true;
-                           }
-                       }
-
-                       if (!error)
-                       {
-                           if (output.data[strlen(output.data) - 1] == '\n')
-                               output.data[strlen(output.data) - 1] = '\0';
-                       }
-
-                       free(file);
-                       if (!error)
-                           options[i] = output.data;
-                       else
-                       {
-                           options[i] = xstrdup("");
-                           termPQExpBuffer(&output);
-                       }
-                       break;
-                   }
-               case 0:
-               default:
-                   if (token[0] == '\\')
-                       continue_parse = options_string + pos;
-                   else if (token[0] == '$') 
-                    {
-                        const char * value = GetVariable(pset.vars, token+1);
-                        if (!value)
-                            value = "";
-                       options[i] = xstrdup(value);
-                    }
-                   else
-                       options[i] = xstrdup(token);
-           }
-
-           if (continue_parse)
-               break;
-
-           token = strtokx(NULL, " \t", "\"'`", '\\', "e, &pos, pset.encoding);
-       } /* for */
-
-        options[i] = NULL;
-   }
-
-   cmd = my_line;
-   status = exec_command(cmd, options, options_string, query_buf);
+   status = exec_command(my_line, options_string, &continue_parse, query_buf);
 
    if (status == CMD_UNKNOWN)
    {
-
        /*
-        * If the command was not recognized, try inserting a space after
-        * the first letter and call again. The one letter commands allow
-        * arguments to start immediately after the command, but that is
-        * no longer encouraged.
+        * If the command was not recognized, try inserting a space after the
+         * first letter and call again. The one letter commands allow arguments
+         * to start immediately after the command, but that is no longer
+         * encouraged.
         */
-       const char *new_options[NR_OPTIONS+1];
        char        new_cmd[2];
-       int         i;
-
-       for (i = 1; i < NR_OPTIONS+1; i++)
-           new_options[i] = options[i - 1];
-       new_options[0] = cmd + 1;
 
-       new_cmd[0] = cmd[0];
+       new_cmd[0] = my_line[0];
        new_cmd[1] = '\0';
 
-       status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf);
+       status = exec_command(new_cmd, my_line + 1, &continue_parse, query_buf);
+
+        if (status != CMD_UNKNOWN && isalpha(new_cmd[0]))
+            psql_error("Warning: this syntax is deprecated\n");
    }
 
    if (status == CMD_UNKNOWN)
    {
         if (pset.cur_cmd_interactive)
-            fprintf(stderr, "Invalid command \\%s. Try \\? for help.\n", cmd);
+            fprintf(stderr, "Invalid command \\%s. Try \\? for help.\n", my_line);
         else
-            psql_error("invalid command \\%s\n", cmd);
+            psql_error("invalid command \\%s\n", my_line);
        status = CMD_ERROR;
    }
 
-   if (continue_parse && *(continue_parse + 1) == '\\')
+   if (continue_parse && *continue_parse && *(continue_parse + 1) == '\\')
        continue_parse += 2;
 
 
@@ -276,10 +150,6 @@ HandleSlashCmds(const char *line,
     else
         *end_of_cmd = line + strlen(line);
 
-   /* clean up */
-   for (i = 0; i < NR_OPTIONS && options[i]; i++)
-       free(options[i]);
-
    free(my_line);
 
    return status;
@@ -287,19 +157,26 @@ HandleSlashCmds(const char *line,
 
 
 
-
 static backslashResult
 exec_command(const char *cmd,
-            char *const * options,
             const char *options_string,
+             const char ** continue_parse,
             PQExpBuffer query_buf)
 {
    bool        success = true; /* indicate here if the command ran ok or
                                 * failed */
    bool        quiet = QUIET();
-
    backslashResult status = CMD_SKIP_LINE;
+    char       *string, *string_cpy;
 
+    /*
+     * The 'string' variable will be overwritten to point to the next token,
+     * hence we need an extra pointer so we can free this at the end.
+     */
+    if (options_string)
+        string = string_cpy = xstrdup(options_string);
+    else
+        string = string_cpy = NULL;
 
    /* \a -- toggle field alignment This makes little sense but we keep it around. */
    if (strcmp(cmd, "a") == 0)
@@ -310,44 +187,53 @@ exec_command(const char *cmd,
            success = do_pset("format", "unaligned", &pset.popt, quiet);
    }
 
-
    /* \C -- override table title (formerly change HTML caption) */
    else if (strcmp(cmd, "C") == 0)
-       success = do_pset("title", options[0], &pset.popt, quiet);
-
+    {
+        char * opt = scan_option(&string, OT_NORMAL, NULL);
+       success = do_pset("title", opt, &pset.popt, quiet);
+        free(opt);
+    }
 
    /*----------
     * \c or \connect -- connect to new database or as different user
     *
-    * \c foo bar: connect to db "foo" as user "bar"
-     * \c foo [-]: connect to db "foo" as current user
-     * \c - bar:   connect to current db as user "bar"
-     * \c:          connect to default db as default user
+    * \c foo bar  connect to db "foo" as user "bar"
+     * \c foo [-]  connect to db "foo" as current user
+     * \c - bar    connect to current db as user "bar"
+     * \c          connect to default db as default user
      *----------
     */
    else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
    {
-       if (options[1])
+        char *opt1, *opt2;
+        char opt1q, opt2q;
+
+        opt1 = scan_option(&string, OT_NORMAL, &opt1q);
+        opt2 = scan_option(&string, OT_NORMAL, &opt2q);
+
+       if (opt2)
            /* gave username */
-           success = do_connect(options[0], options[1]);
-       else
-       {
-           if (options[0])
-               /* gave database name */
-               success = do_connect(options[0], "");       /* empty string is same
-                                                             * username as before,
-                                                             * NULL would mean libpq
-                                                             * default */
-           else
-               /* connect to default db as default user */
-               success = do_connect(NULL, NULL);
-       }
-   }
+           success = do_connect(!opt1q && (strcmp(opt1, "-")==0 || strcmp(opt1, "")==0) ? "" : opt1,
+                                 !opt2q && (strcmp(opt2, "-")==0 || strcmp(opt2, "")==0) ? "" : opt2);
+       else if (opt1)
+            /* gave database name */
+            success = do_connect(!opt1q && (strcmp(opt1, "-")==0 || strcmp(opt1, "")==0) ? "" : opt1, "");
+        else
+            /* connect to default db as default user */
+            success = do_connect(NULL, NULL);
 
+        free(opt1);
+        free(opt2);
+   }
 
    /* \copy */
    else if (strcasecmp(cmd, "copy") == 0)
+    {
        success = do_copy(options_string);
+        if (options_string)
+            string += strlen(string);
+    }
 
    /* \copyright */
    else if (strcmp(cmd, "copyright") == 0)
@@ -356,38 +242,42 @@ exec_command(const char *cmd,
    /* \d* commands */
    else if (cmd[0] == 'd')
    {
-        bool show_verbose = strchr(cmd, '+') ? true : false;
+        char * name;
+        bool show_verbose;
+
+        name = scan_option(&string, OT_SQLID, NULL);
+        show_verbose = strchr(cmd, '+') ? true : false;
 
        switch (cmd[1])
        {
            case '\0':
             case '+':
-               if (options[0])
-                   success = describeTableDetails(options[0], show_verbose);
+               if (name)
+                   success = describeTableDetails(name, show_verbose);
                else
                     /* standard listing of interesting things */
                    success = listTables("tvs", NULL, show_verbose);
                break;
            case 'a':
-               success = describeAggregates(options[0]);
+               success = describeAggregates(name);
                break;
            case 'd':
-               success = objectDescription(options[0]);
+               success = objectDescription(name);
                break;
            case 'f':
-               success = describeFunctions(options[0], show_verbose);
+               success = describeFunctions(name, show_verbose);
                break;
            case 'l':
                success = do_lo_list();
                break;
            case 'o':
-               success = describeOperators(options[0]);
+               success = describeOperators(name);
                break;
            case 'p':
-               success = permissionsList(options[0]);
+               success = permissionsList(name);
                break;
            case 'T':
-               success = describeTypes(options[0], show_verbose);
+               success = describeTypes(name, show_verbose);
                break;
            case 't':
            case 'v':
@@ -397,11 +287,12 @@ exec_command(const char *cmd,
                if (cmd[1] == 'S' && cmd[2] == '\0')
                    success = listTables("Stvs", NULL, show_verbose);
                else
-                   success = listTables(&cmd[1], options[0], show_verbose);
+                   success = listTables(&cmd[1], name, show_verbose);
                break;
            default:
                status = CMD_UNKNOWN;
        }
+        free(name);
    }
 
 
@@ -410,46 +301,81 @@ exec_command(const char *cmd,
     * the query buffer
     */
    else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
-       status = do_edit(options[0], query_buf) ? CMD_NEWEDIT : CMD_ERROR;
+    {
+        char * fname;
 
+        if (!query_buf)
+        {
+            psql_error("no query buffer");
+            status = CMD_ERROR;
+        }
+        else
+        {
+            fname = scan_option(&string, OT_NORMAL, NULL);
+            status = do_edit(fname, query_buf) ? CMD_NEWEDIT : CMD_ERROR;
+            free(fname);
+        }
+    }
 
-   /* \echo */
-   else if (strcmp(cmd, "echo") == 0)
+   /* \echo and \qecho */
+   else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho")==0)
    {
-       int         i;
+        char * value;
+        char quoted;
+        bool no_newline = false;
+        bool first = true;
+        FILE * fout;
+
+        if (strcmp(cmd, "qecho")==0)
+            fout = pset.queryFout;
+        else
+            fout = stdout;
 
-       for (i = 0; i < 16 && options[i]; i++)
-           fputs(options[i], stdout);
-       fputs("\n", stdout);
+        while((value = scan_option(&string, OT_NORMAL, "ed)))
+        {
+            if (!quoted && strcmp(value, "-n")==0)
+                no_newline = true;
+            else
+            {
+                if (first)
+                    first = false;
+                else
+                    fputc(' ', fout);
+                fputs(value, fout);
+            }
+            free(value);
+        }
+        if (!no_newline)
+            fputs("\n", fout);
    }
 
    /* \f -- change field separator */
    else if (strcmp(cmd, "f") == 0)
-       success = do_pset("fieldsep", options[0], &pset.popt, quiet);
+    {
+        char * fname = scan_option(&string, OT_NORMAL, NULL);
+       success = do_pset("fieldsep", fname, &pset.popt, quiet);
+        free(fname);
+    }
 
    /* \g means send query */
    else if (strcmp(cmd, "g") == 0)
    {
-       if (!options[0])
+        char * fname = scan_option(&string, OT_NORMAL, NULL);
+       if (!fname)
            pset.gfname = NULL;
        else
-           pset.gfname = xstrdup(options[0]);
+           pset.gfname = xstrdup(fname);
+        free(fname);
        status = CMD_SEND;
    }
 
    /* help */
    else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
     {
-        char buf[256] = "";
-        int i;
-        for (i=0; options && options[i] && strlen(buf)<255; i++)
-        {
-            strncat(buf, options[i], 255 - strlen(buf));
-            if (strlen(buf)<255 && options[i+1])
-                strcat(buf, " ");
-        }
-        buf[255] = '\0';
-       helpSQL(buf);
+       helpSQL(options_string ? &options_string[strspn(options_string, " \t")] : NULL);
+        /* set pointer to end of line */
+        if (string)
+            string += strlen(string);
     }
 
    /* HTML mode */
@@ -465,46 +391,55 @@ exec_command(const char *cmd,
    /* \i is include file */
    else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
    {
-       if (!options[0])
+        char * fname = scan_option(&string, OT_NORMAL, NULL);
+       if (!fname)
         {
             psql_error("\\%s: missing required argument\n", cmd);
            success = false;
        }
        else
-           success = process_file(options[0]);
+        {
+           success = process_file(fname);
+            free (fname);
+        }
    }
 
-
    /* \l is list databases */
    else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
        success = listAllDbs(false);
    else if (strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
        success = listAllDbs(true);
 
-
-   /* large object things */
+   /*
+     * large object things
+     */
    else if (strncmp(cmd, "lo_", 3) == 0)
    {
+        char *opt1, *opt2;
+
+        opt1 = scan_option(&string, OT_NORMAL, NULL);
+        opt2 = scan_option(&string, OT_NORMAL, NULL);
+
        if (strcmp(cmd + 3, "export") == 0)
        {
-           if (!options[1])
+           if (!opt2)
            {
                 psql_error("\\%s: missing required argument\n", cmd);
                success = false;
            }
            else
-               success = do_lo_export(options[0], options[1]);
+               success = do_lo_export(opt1, opt2);
        }
 
        else if (strcmp(cmd + 3, "import") == 0)
        {
-           if (!options[0])
+           if (!opt1)
            {
                 psql_error("\\%s: missing required argument\n", cmd);
                success = false;
            }
            else
-               success = do_lo_import(options[0], options[1]);
+               success = do_lo_import(opt1, opt2);
        }
 
        else if (strcmp(cmd + 3, "list") == 0)
@@ -512,23 +447,30 @@ exec_command(const char *cmd,
 
        else if (strcmp(cmd + 3, "unlink") == 0)
        {
-           if (!options[0])
+           if (!opt1)
            {
                 psql_error("\\%s: missing required argument\n", cmd);
                success = false;
            }
            else
-               success = do_lo_unlink(options[0]);
+               success = do_lo_unlink(opt1);
        }
 
        else
            status = CMD_UNKNOWN;
+
+        free(opt1);
+        free(opt2);
    }
 
+
    /* \o -- set query output */
    else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
-       success = setQFout(options[0]);
-
+    {
+        char * fname = scan_option(&string, OT_NORMAL, NULL);
+       success = setQFout(fname);
+        free(fname);
+    }
 
    /* \p prints the current query buffer */
    else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
@@ -543,29 +485,24 @@ exec_command(const char *cmd,
    /* \pset -- set printing parameters */
    else if (strcmp(cmd, "pset") == 0)
    {
-       if (!options[0])
+        char * opt0 = scan_option(&string, OT_NORMAL, NULL);
+        char * opt1 = scan_option(&string, OT_NORMAL, NULL);
+       if (!opt0)
        {
             psql_error("\\%s: missing required argument\n", cmd);
            success = false;
        }
        else
-           success = do_pset(options[0], options[1], &pset.popt, quiet);
+           success = do_pset(opt0, opt1, &pset.popt, quiet);
+
+        free(opt0);
+        free(opt1);
    }
 
    /* \q or \quit */
    else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
        status = CMD_TERMINATE;
 
-   /* \qecho */
-   else if (strcmp(cmd, "qecho") == 0)
-   {
-       int         i;
-
-       for (i = 0; i < 16 && options[i]; i++)
-           fputs(options[i], pset.queryFout);
-       fputs("\n", pset.queryFout);
-   }
-
    /* reset(clear) the buffer */
    else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
    {
@@ -574,34 +511,31 @@ exec_command(const char *cmd,
            puts("Query buffer reset (cleared).");
    }
 
-
    /* \s save history in a file or show it on the screen */
    else if (strcmp(cmd, "s") == 0)
    {
-       const char *fname;
+       char *fname = scan_option(&string, OT_NORMAL, NULL);
 
-       if (!options[0])
-           fname = "/dev/tty";
-       else
-           fname = options[0];
-
-       success = saveHistory(fname);
+       success = saveHistory(fname ? fname : "/dev/tty");
 
-       if (success && !quiet && options[0])
+       if (success && !quiet && fname)
            printf("Wrote history to %s.\n", fname);
+        free(fname);
    }
 
-
-   /* \set -- generalized set option command */
+   /* \set -- generalized set variable/option command */
    else if (strcmp(cmd, "set") == 0)
    {
-       if (!options[0])
+        char * opt0 = scan_option(&string, OT_NORMAL, NULL);
+
+       if (!opt0)
        {
            /* list all variables */
 
            /*
-            * (This is in utter violation of the GetVariable abstraction,
-            * but I have not dreamt up a better way.)
+            * XXX
+             * This is in utter violation of the GetVariable abstraction, but I
+             * have not bothered to do it better.
             */
            struct _variable *ptr;
 
@@ -611,15 +545,36 @@ exec_command(const char *cmd,
        }
        else
        {
-            const char * val = options[1];
-            if (!val)
-                val = "";
-           if (!SetVariable(pset.vars, options[0], val))
+            /*
+             * Set variable to the concatenation of the arguments.
+             */
+            char * newval = NULL;
+            char * opt;
+
+            opt = scan_option(&string, OT_NORMAL, NULL);
+            newval = xstrdup(opt ? opt : "");
+            free(opt);
+
+            while ((opt = scan_option(&string, OT_NORMAL, NULL)))
+            {
+                newval = realloc(newval, strlen(newval) + strlen(opt) + 1);
+                if (!newval)
+                {
+                    psql_error("out of memory");
+                    exit(EXIT_FAILURE);
+                }
+                strcat(newval, opt);
+                free(opt);
+            }
+
+           if (!SetVariable(pset.vars, opt0, newval))
            {
                 psql_error("\\%s: error\n", cmd);
                success = false;
            }
+            free(newval);
        }
+        free(opt0);
    }
 
    /* \t -- turn off headers and row count */
@@ -629,48 +584,67 @@ exec_command(const char *cmd,
 
    /* \T -- define html  attributes */
    else if (strcmp(cmd, "T") == 0)
-       success = do_pset("tableattr", options[0], &pset.popt, quiet);
+    {
+        char * value = scan_option(&string, OT_NORMAL, NULL);
+       success = do_pset("tableattr", value, &pset.popt, quiet);
+        free(value);
+    }
 
     /* \unset */
     else if (strcmp(cmd, "unset") == 0)
     {
-        if (!SetVariable(pset.vars, options[0], NULL))
+        char * opt = scan_option(&string, OT_NORMAL, NULL);
+        if (!opt)
+        {
+            psql_error("\\%s: missing required argument", cmd);
+            success = false;
+        }
+        if (!SetVariable(pset.vars, opt, NULL))
         {
             psql_error("\\%s: error\n", cmd);
-
             success = false;
-           }
+        }
+        free(opt);
     }
 
    /* \w -- write query buffer to file */
    else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
    {
        FILE       *fd = NULL;
-       bool        pipe = false;
+       bool        is_pipe = false;
+        char       *fname = NULL;
 
-       if (!options[0])
-       {
-            psql_error("\\%s: missing required argument\n", cmd);
-           success = false;
-       }
-       else
-       {
-           if (options[0][0] == '|')
-           {
-               pipe = true;
-               fd = popen(&options[0][1], "w");
-           }
-           else
-           {
-               fd = fopen(options[0], "w");
-           }
+        if (!query_buf)
+        {
+            psql_error("no query buffer");
+            status = CMD_ERROR;
+        }
+        else
+        {
+            fname = scan_option(&string, OT_NORMAL, NULL);
 
-           if (!fd)
-           {
-                psql_error("%s: %s\n", options[0], strerror(errno));
-               success = false;
-           }
-       }
+            if (!fname)
+            {
+                psql_error("\\%s: missing required argument\n", cmd);
+                success = false;
+            }
+            else
+            {
+                if (fname[0] == '|')
+                {
+                    is_pipe = true;
+                    fd = popen(&fname[1], "w");
+                }
+                else
+                    fd = fopen(fname, "w");
+
+                if (!fd)
+                {
+                    psql_error("%s: %s\n", fname, strerror(errno));
+                    success = false;
+                }
+            }
+        }
 
        if (fd)
        {
@@ -679,17 +653,19 @@ exec_command(const char *cmd,
            if (query_buf && query_buf->len > 0)
                fprintf(fd, "%s\n", query_buf->data);
 
-           if (pipe)
+           if (is_pipe)
                result = pclose(fd);
            else
                result = fclose(fd);
 
            if (result == EOF)
            {
-                psql_error("%s: %s\n", options[0], strerror(errno));
+                psql_error("%s: %s\n", fname, strerror(errno));
                success = false;
            }
        }
+
+        free(fname);
    }
 
    /* \x -- toggle expanded table representation */
@@ -697,30 +673,43 @@ exec_command(const char *cmd,
        success = do_pset("expanded", NULL, &pset.popt, quiet);
 
 
-   /* list table rights (grant/revoke) */
+   /* \z -- list table rights (grant/revoke) */
    else if (strcmp(cmd, "z") == 0)
-       success = permissionsList(options[0]);
-
+    {
+        char * opt = scan_option(&string, OT_SQLID, NULL);
+       success = permissionsList(opt);
+        free(opt);
+    }
 
+    /* \! -- shell escape */
    else if (strcmp(cmd, "!") == 0)
+    {
        success = do_shell(options_string);
+        /* wind pointer to end of line */
+        if (string)
+            string += strlen(string);
+    }
 
+    /* \? -- slash command help */
    else if (strcmp(cmd, "?") == 0)
        slashUsage();
 
-
-#if 0
+#if 1
     /*
     * These commands don't do anything. I just use them to test the
     * parser.
     */
    else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0)
    {
-       int         i;
+       int         i = 0;
+        char       *value;
 
-       fprintf(stderr, "+ optline = |%s|\n", options_string);
-       for (i = 0; options[i]; i++)
-           fprintf(stderr, "+ opt%d = |%s|\n", i, options[i]);
+       fprintf(stderr, "+ optstr = |%s|\n", options_string);
+        while((value = scan_option(&string, OT_NORMAL, NULL)))
+        {
+           fprintf(stderr, "+ opt(%d) = |%s|\n", i++, value);
+            free(value);
+        }
    }
 #endif
 
@@ -729,23 +718,300 @@ exec_command(const char *cmd,
 
    if (!success)
        status = CMD_ERROR;
+
+    /* eat the rest of the options string */
+    while(scan_option(&string, OT_NORMAL, NULL)) ;
+
+    if (options_string && continue_parse)
+        *continue_parse = options_string + (string - string_cpy);
+    free(string_cpy);
+
    return status;
 }
 
 
 
+/*
+ * scan_option()
+ */
+static char *
+scan_option(char ** string, enum option_type type, char * quote)
+{
+    unsigned int pos = 0;
+    char * options_string;
+    char * return_val;
+
+    if (quote)
+        *quote = 0;
+
+    if (!string || !(*string))
+        return NULL;
+
+    options_string = *string;
+    /* skip leading whitespace */
+    pos += strspn(options_string+pos, " \t");
+
+    switch (options_string[pos])
+    {
+        /*
+         * Double quoted string
+         */
+        case '"':
+        {
+            unsigned int jj;
+            unsigned short int bslash_count = 0;
+
+            /* scan for end of quote */
+            for (jj = pos+1; options_string[jj]; jj += PQmblen(&options_string[jj], pset.encoding))
+            {
+                if (options_string[jj] == '"' && bslash_count % 2 == 0)
+                    break;
+
+                if (options_string[jj] == '\\')
+                    bslash_count++;
+                else
+                    bslash_count=0;
+            }
+
+            if (options_string[jj] == 0)
+            {
+                psql_error("parse error at end of line\n");
+                *string = &options_string[jj];
+                return NULL;
+            }
+
+            return_val = malloc(jj-pos+2);
+            if (!return_val)
+            {
+                psql_error("out of memory\n");
+                exit(EXIT_FAILURE);
+            }
+
+            if (type == OT_NORMAL)
+            {
+                strncpy(return_val, &options_string[pos], jj-pos+1);
+                return_val[jj-pos+1] = '\0';
+            }
+            /*
+             * If this is expected to be an SQL identifier like option
+             * then we strip out the double quotes
+             */
+            else if (type == OT_SQLID)
+            {
+                unsigned int k, cc;
+
+                bslash_count = 0;
+                cc = 0;
+                for (k = pos+1; options_string[k]; k += PQmblen(&options_string[k], pset.encoding))
+                {   
+                    if (options_string[k] == '"' && bslash_count % 2 == 0)
+                        break;
+                                        
+                    if (options_string[jj] == '\\')
+                        bslash_count++;
+                    else
+                        bslash_count=0;
+                    
+                    return_val[cc++] = options_string[k];
+                }
+                return_val[cc] = '\0';
+            }       
+                    
+            *string = options_string + jj+1;
+            if (quote)
+                *quote = '"';
+                    
+            return return_val;
+        }           
+
+        /*
+         * A single quote has a psql internal meaning, such as
+         * for delimiting file names, and it also allows for such
+         * escape sequences as \t.
+         */
+        case '\'':
+        {
+            unsigned int jj;
+            unsigned short int bslash_count = 0;
+
+            for (jj = pos+1; options_string[jj]; jj += PQmblen(&options_string[jj], pset.encoding))
+            {
+                if (options_string[jj] == '\'' && bslash_count % 2 == 0)
+                    break;
+
+                if (options_string[jj] == '\\')
+                    bslash_count++;
+                else
+                    bslash_count=0;
+            }
+
+            if (options_string[jj] == 0)
+            {
+                psql_error("parse error at end of line\n");
+                *string = &options_string[jj];
+                return NULL;
+            }
+
+            return_val = unescape(&options_string[pos+1], jj-pos-1);
+            *string = &options_string[jj + 1];
+            if (quote)
+                *quote = '\'';
+            return return_val;
+        }
+
+        /*
+         * Backticks are for command substitution, like in shells
+         */
+        case '`':
+        {
+            bool       error = false;
+            FILE      *fd = NULL;
+            char      *file;
+            PQExpBufferData output;
+            char       buf[512];
+            size_t     result, len;
+
+            len = strcspn(options_string + pos + 1, "`");
+            if (options_string[pos + 1 + len] == 0)
+            {
+                psql_error("parse error at end of line\n");
+                *string = &options_string[pos + 1 + len];
+                return NULL;
+            }
+
+            options_string[pos + 1 + len] = '\0';
+            file = options_string + pos + 1;
+
+            fd = popen(file, "r");
+            if (!fd)
+            {
+                psql_error("%s: %s\n", file, strerror(errno));
+                error = true;
+            }
+
+            if (!error)
+            {
+                initPQExpBuffer(&output);
+
+                do
+                {
+                    result = fread(buf, 1, 512, fd);
+                    if (ferror(fd))
+                    {
+                        psql_error("%s: %s\n", file, strerror(errno));
+                        error = true;
+                        break;
+                    }
+                    appendBinaryPQExpBuffer(&output, buf, result);
+                } while (!feof(fd));
+                appendPQExpBufferChar(&output, '\0');
+
+                if (pclose(fd) == -1)
+                {
+                    psql_error("%s: %s\n", file, strerror(errno));
+                    error = true;
+                }
+            }
+
+            if (!error)
+            {
+                if (output.data[strlen(output.data) - 1] == '\n')
+                    output.data[strlen(output.data) - 1] = '\0';
+            }
+
+            if (!error)
+                return_val = output.data;
+            else
+            {
+                return_val = xstrdup("");
+                termPQExpBuffer(&output);
+            }
+            options_string[pos + 1 + len] = '`';
+            *string = options_string + pos + len + 2;
+            if (quote)
+                *quote = '`';
+            return return_val;
+        }
+
+        /*
+         * end of line
+         */
+        case 0:
+            *string = &options_string[pos];
+            return NULL;
+
+        /*
+         * Variable substitution
+         */
+        case ':':
+        {
+            size_t token_end;
+            const char * value;
+            char save_char;
+            
+            token_end = strcspn(&options_string[pos+1], " \t");
+            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];
+            return return_val;
+        }
+
+        /*
+         * Next command
+         */
+        case '\\':
+            *string = options_string + pos;
+            return NULL;
+            break;
+
+        /*
+         * A normal word
+         */
+        default:
+        {
+            size_t token_end;
+            char * cp;
+            
+            token_end = strcspn(&options_string[pos], " \t");
+            return_val = malloc(token_end + 1);
+            if (!return_val)
+            {
+                psql_error("out of memory\n");
+                exit(EXIT_FAILURE);
+            }
+            strncpy(return_val, &options_string[pos], token_end);
+            return_val[token_end] = 0;
+
+            if (type == OT_SQLID)
+                for (cp = return_val; *cp; cp += PQmblen(cp, pset.encoding))
+                    if (isascii(*cp))
+                        *cp = tolower(*cp);
+
+            *string = &options_string[pos+token_end];
+            return return_val;
+        }
+            
+    }
+}
+
+
+
 /*
  * unescape
  *
  * Replaces \n, \t, and the like.
- * Also interpolates ${variables}.
  *
  * The return value is malloc()'ed.
  */
 static char *
-unescape(const char *source)
+unescape(const unsigned char *source, size_t len)
 {
-   unsigned char *p;
+   const unsigned char *p;
    bool        esc = false;    /* Last character we saw was the escape
                                 * character */
    char       *destination,
@@ -756,16 +1022,16 @@ unescape(const char *source)
    assert(source);
 #endif
 
-   length = strlen(source) + 1;
+   length = Min(len, strlen(source)) + 1;
 
-   tmp = destination = (char *) malloc(length);
+   tmp = destination = malloc(length);
    if (!tmp)
    {
        psql_error("out of memory\n");
        exit(EXIT_FAILURE);
    }
 
-   for (p = (char *) source; *p; p += PQmblen(p, pset.encoding))
+   for (p = source; p-source < len && *p; p += PQmblen(p, pset.encoding))
    {
        if (esc)
        {
@@ -776,12 +1042,15 @@ unescape(const char *source)
                case 'n':
                    c = '\n';
                    break;
-               case 'r':
-                   c = '\r';
-                   break;
                case 't':
                    c = '\t';
                    break;
+               case 'b':
+                   c = '\b';
+                   break;
+               case 'r':
+                   c = '\r';
+                   break;
                case 'f':
                    c = '\f';
                    break;
@@ -814,44 +1083,6 @@ unescape(const char *source)
        else if (*p == '\\')
            esc = true;
 
-       else if (*p == '$')
-       {
-           if (*(p + 1) == '{')
-           {
-               unsigned int len;
-               char       *copy;
-               const char *value;
-#ifndef WIN32
-               void       *new;
-#else
-               char *new;
-#endif
-
-               len = strcspn(p + 2, "}");
-               copy = xstrdup(p + 2);
-               copy[len] = '\0';
-               value = GetVariable(pset.vars, copy);
-                if (!value)
-                    value = "";
-               length += strlen(value) - (len + 3);
-               new = realloc(destination, length);
-               if (!new)
-               {
-                   psql_error("out of memory\n");
-                   exit(EXIT_FAILURE);
-               }
-               tmp = new + (tmp - destination);
-               destination = new;
-
-               strcpy(tmp, value);
-               tmp += strlen(value);
-               p += len + 2;
-               free(copy);
-           }
-           else
-               *tmp++ = '$';
-       }
-
        else
        {
            *tmp++ = *p;
@@ -865,7 +1096,6 @@ unescape(const char *source)
 
 
 
-
 /* do_connect
  * -- handler for \connect
  *
@@ -893,8 +1123,8 @@ do_connect(const char *new_dbname, const char *new_user)
     SetVariable(pset.vars, "HOST", NULL);
     SetVariable(pset.vars, "PORT", NULL);
 
-   /* If dbname is "-" then use old name, else new one (even if NULL) */
-   if (oldconn && new_dbname && PQdb(oldconn) && strcmp(new_dbname, "-") == 0)
+   /* If dbname is "" then use old name, else new one (even if NULL) */
+   if (oldconn && new_dbname && PQdb(oldconn) && strcmp(new_dbname, "") == 0)
        dbparam = PQdb(oldconn);
    else
        dbparam = new_dbname;
@@ -1001,7 +1231,7 @@ do_connect(const char *new_dbname, const char *new_user)
 
 /*
  * Test if the given user is a database superuser.
- * (Used to set up the prompt right.)
+ * (Is used to set up the prompt right.)
  */
 bool
 test_superuser(const char * username)
@@ -1037,7 +1267,7 @@ test_superuser(const char * username)
 static bool
 editFile(const char *fname)
 {
-   char       *editorName;
+   const char *editorName;
    char       *sys;
    int         result;
 
@@ -1063,7 +1293,7 @@ editFile(const char *fname)
    sprintf(sys, "exec %s %s", editorName, fname);
    result = system(sys);
    if (result == -1)
-        psql_error("could not start editor\n");
+        psql_error("could not start editor %s\n", editorName);
     else if (result == 127)
        psql_error("could not start /bin/sh\n");
    free(sys);
@@ -1087,14 +1317,6 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
 
 #endif
 
-#ifdef USE_ASSERT_CHECKING
-   assert(query_buf);
-#else
-   if (!query_buf)
-       return false;
-#endif
-
-
    if (filename_arg)
        fname = filename_arg;
 
@@ -1233,11 +1455,7 @@ process_file(char *filename)
    if (!filename)
        return false;
 
-#ifdef __CYGWIN32__
-   fd = fopen(filename, "rb");
-#else
    fd = fopen(filename, "r");
-#endif
 
    if (!fd)
    {
@@ -1454,7 +1672,7 @@ do_pset(const char *param, const char *value, printQueryOpt * popt, bool quiet)
 
 
 
-#define DEFAULT_SHELL  "/bin/sh"
+#define DEFAULT_SHELL "/bin/sh"
 
 static bool
 do_shell(const char *command)
@@ -1464,7 +1682,7 @@ do_shell(const char *command)
    if (!command)
    {
        char       *sys;
-       char       *shellName;
+       const char *shellName;
 
        shellName = getenv("SHELL");
        if (shellName == NULL)
index 700542cd4d1fb4448592e59383bf9ee28805c45b..084d8790e6f25734fd8b9912131a094cd08c9802 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.11 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.12 2000/02/07 23:10:06 petere Exp $
  */
 #include 
 #include "common.h"
@@ -24,6 +24,7 @@
 #include                 /* for write() */
 #else
 #include                  /* for _write() */
+#include 
 #endif
 
 #include 
 #include "prompt.h"
 #include "print.h"
 
-#ifdef WIN32
-#define popen(x,y) _popen(x,y)
-#define pclose(x) _pclose(x)
-#define write(a,b,c) _write(a,b,c)
-#endif
-
 
 
-/* xstrdup()
- *
+/*
  * "Safe" wrapper around strdup()
- * (Using this also avoids writing #ifdef HAVE_STRDUP in every file :)
  */
 char *
 xstrdup(const char *string)
@@ -57,7 +50,8 @@ xstrdup(const char *string)
 
    if (!string)
    {
-       fprintf(stderr, "%s: xstrdup: cannot duplicate null pointer\n", pset.progname);
+       fprintf(stderr, "%s: xstrdup: cannot duplicate null pointer (internal error)\n",
+                pset.progname);
        exit(EXIT_FAILURE);
    }
    tmp = strdup(string);
@@ -133,7 +127,7 @@ setQFout(const char *fname)
 
 /*
  * Error reporting for scripts. Errors should look like
- *   filename:lineno: message
+ *   psql:filename:lineno: message
  *
  */
 void
@@ -152,8 +146,11 @@ psql_error(const char *fmt, ...)
     va_end(ap);
 }
 
-/* for backend NOTICES */
 
+
+/*
+ * for backend NOTICES
+ */
 void
 NoticeProcessor(void * arg, const char * message)
 {
@@ -184,7 +181,6 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
 #ifdef HAVE_TERMIOS_H
    struct termios t_orig,
                t;
-
 #endif
 
    destination = (char *) malloc(maxlen + 2);
@@ -240,8 +236,8 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
  * Before we start a query, we enable a SIGINT signal catcher that sends a
  * cancel request to the backend. Note that sending the cancel directly from
  * the signal handler is safe because PQrequestCancel() is written to make it
- * so. We have to be very careful what else we do in the signal handler. This
- * includes using write() for output.
+ * so. We use write() to print to stdout because it's better to use simple
+ * facilities in a signal handler.
  */
 
 static PGconn *cancelConn;
index f802d5ed791ffe798152078c3b77bf5605d2d893..638b96600f8641474efe72e05a3200724e3b3dc1 100644 (file)
@@ -5,7 +5,7 @@
 #
 # Copyright 2000 by PostgreSQL Global Development Group
 #
-# $Header: /cvsroot/pgsql/src/bin/psql/create_help.pl,v 1.3 2000/01/29 16:58:48 petere Exp $
+# $Header: /cvsroot/pgsql/src/bin/psql/create_help.pl,v 1.4 2000/02/07 23:10:06 petere Exp $
 #################################################################
 
 #
@@ -56,6 +56,8 @@ struct _helpStruct
 static struct _helpStruct QL_HELP[] = {
 ";
 
+$count = 0;
+
 foreach $file (sort readdir DIR) {
     my ($cmdname, $cmddesc, $cmdsynopsis);
     $file =~ /\.sgml$/ || next;
@@ -84,6 +86,7 @@ foreach $file (sort readdir DIR) {
         $cmdsynopsis =~ s/\"/\\"/g;
 
    print OUT "    { \"$cmdname\",\n      \"$cmddesc\",\n      \"$cmdsynopsis\" },\n\n";
+        $count++;
     }
     else {
    print STDERR "$0: parsing file '$file' failed at or near line $. (N='$cmdname' D='$cmddesc')\n";
@@ -94,6 +97,10 @@ print OUT "
     { NULL, NULL, NULL }    /* End of list marker */
 };
 
+
+#define QL_HELP_COUNT $count
+
+
 #endif /* $define */
 ";
 
index bb259b31d37acff9a31fc19e4cbdade8c6173b34..6ab7c2f519e082bbb2564c672d60b1bcf9f308d7 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.15 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.16 2000/02/07 23:10:06 petere Exp $
  */
 #include 
 #include "describe.h"
@@ -56,7 +56,7 @@ describeAggregates(const char *name)
 
    if (name)
    {
-       strcat(buf, "  AND a.aggname ~* '");
+       strcat(buf, "  AND a.aggname ~* '^");
        strncat(buf, name, REGEXP_CUTOFF);
        strcat(buf, "'\n");
    }
@@ -71,7 +71,7 @@ describeAggregates(const char *name)
 
    if (name)
    {
-       strcat(buf, "  AND a.aggname ~* '");
+       strcat(buf, "  AND a.aggname ~* '^");
        strncat(buf, name, REGEXP_CUTOFF);
        strcat(buf, "'\n");
    }
@@ -125,7 +125,7 @@ describeFunctions(const char *name, bool verbose)
 
    if (name)
    {
-       strcat(buf, "  AND p.proname ~* '");
+       strcat(buf, "  AND p.proname ~* '^");
        strncat(buf, name, REGEXP_CUTOFF);
        strcat(buf, "'\n");
    }
@@ -169,7 +169,7 @@ describeTypes(const char *name, bool verbose)
 
    if (name)
    {
-       strcat(buf, "  AND t.typname ~* '");
+       strcat(buf, "  AND t.typname ~* '^");
        strncat(buf, name, REGEXP_CUTOFF);
        strcat(buf, "' ");
    }
@@ -215,7 +215,7 @@ describeOperators(const char *name)
           "       o.oprright = t2.oid\n");
    if (name)
    {
-       strcat(buf, "  AND o.oprname ~ '");
+       strcat(buf, "  AND o.oprname ~ '^");
        strncat(buf, name, REGEXP_CUTOFF);
        strcat(buf, "'\n");
    }
@@ -233,7 +233,7 @@ describeOperators(const char *name)
           "       o.oprright = t1.oid\n");
    if (name)
    {
-       strcat(buf, "AND o.oprname ~ '");
+       strcat(buf, "AND o.oprname ~ '^");
        strncat(buf, name, REGEXP_CUTOFF);
        strcat(buf, "'\n");
    }
@@ -251,7 +251,7 @@ describeOperators(const char *name)
           "       o.oprleft = t1.oid\n");
    if (name)
    {
-       strcat(buf, "AND o.oprname ~ '");
+       strcat(buf, "AND o.oprname ~ '^");
        strncat(buf, name, REGEXP_CUTOFF);
        strcat(buf, "'\n");
    }
@@ -346,7 +346,7 @@ permissionsList(const char *name)
           "       relname !~ '^pg_'\n");
    if (name)
    {
-       strcat(descbuf, "  AND relname ~ '");
+       strcat(descbuf, "  AND relname ~ '^");
        strncat(descbuf, name, REGEXP_CUTOFF);
        strcat(descbuf, "'\n");
    }
@@ -391,7 +391,7 @@ objectDescription(const char *object)
           "WHERE a.oid = d.objoid\n");
    if (object)
    {
-       strcat(descbuf, "  AND a.aggname ~* '");
+       strcat(descbuf, "  AND a.aggname ~* '^");
        strncat(descbuf, object, REGEXP_CUTOFF);
        strcat(descbuf, "'\n");
    }
@@ -403,7 +403,7 @@ objectDescription(const char *object)
           "WHERE p.oid = d.objoid AND (p.pronargs = 0 or oidvectortypes(p.proargtypes) != '')\n");
    if (object)
    {
-       strcat(descbuf, "  AND p.proname ~* '");
+       strcat(descbuf, "  AND p.proname ~* '^");
        strncat(descbuf, object, REGEXP_CUTOFF);
        strcat(descbuf, "'\n");
    }
@@ -416,7 +416,7 @@ objectDescription(const char *object)
           "WHERE RegprocToOid(o.oprcode) = d.objoid\n");
    if (object)
    {
-       strcat(descbuf, "  AND o.oprname ~ '");
+       strcat(descbuf, "  AND o.oprname ~ '^");
        strncat(descbuf, object, REGEXP_CUTOFF);
        strcat(descbuf, "'\n");
    }
@@ -428,7 +428,7 @@ objectDescription(const char *object)
           "WHERE t.oid = d.objoid\n");
    if (object)
    {
-       strcat(descbuf, "  AND t.typname ~* '");
+       strcat(descbuf, "  AND t.typname ~* '^");
        strncat(descbuf, object, REGEXP_CUTOFF);
        strcat(descbuf, "'\n");
    }
@@ -440,7 +440,7 @@ objectDescription(const char *object)
           "WHERE c.oid = d.objoid\n");
    if (object)
    {
-       strcat(descbuf, "  AND c.relname ~* '");
+       strcat(descbuf, "  AND c.relname ~* '^");
        strncat(descbuf, object, REGEXP_CUTOFF);
        strcat(descbuf, "'\n");
    }
@@ -452,7 +452,7 @@ objectDescription(const char *object)
           "WHERE r.oid = d.objoid AND r.rulename !~ '^_RET'\n");
    if (object)
    {
-       strcat(descbuf, "  AND r.rulename ~* '");
+       strcat(descbuf, "  AND r.rulename ~* '^");
        strncat(descbuf, object, REGEXP_CUTOFF);
        strcat(descbuf, "'\n");
    }
@@ -464,7 +464,7 @@ objectDescription(const char *object)
           "WHERE t.oid = d.objoid\n");
    if (object)
    {
-       strcat(descbuf, "  AND t.tgname ~* '");
+       strcat(descbuf, "  AND t.tgname ~* '^");
        strncat(descbuf, object, REGEXP_CUTOFF);
        strcat(descbuf, "'\n");
    }
@@ -504,7 +504,7 @@ xmalloc(size_t size)
    tmp = malloc(size);
    if (!tmp)
    {
-       psql_error("out of memory");
+       psql_error("out of memory\n");
        exit(EXIT_FAILURE);
    }
    return tmp;
@@ -626,7 +626,7 @@ describeTableDetails(const char *name, bool desc)
         bool        isarray = false;
 
        /* Name */
-       cells[i * cols + 0] = (char *)PQgetvalue(res, i, 0);    /* don't free this afterwards */
+       cells[i * cols + 0] = PQgetvalue(res, i, 0);    /* don't free this afterwards */
 
        /* Type */
         if (attype[0] == '_')
@@ -701,7 +701,7 @@ describeTableDetails(const char *name, bool desc)
         
        /* Description */
        if (desc)
-           cells[i * cols + cols-1] = (char*)PQgetvalue(res, i, 7);
+           cells[i * cols + cols-1] = PQgetvalue(res, i, 7);
    }
 
    /* Make title */
@@ -960,7 +960,7 @@ listTables(const char *infotype, const char *name, bool desc)
        strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
        if (name)
        {
-           strcat(buf, "  AND c.relname ~ '");
+           strcat(buf, "  AND c.relname ~ '^");
            strncat(buf, name, REGEXP_CUTOFF);
            strcat(buf, "'\n");
        }
@@ -976,7 +976,7 @@ listTables(const char *infotype, const char *name, bool desc)
        strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
        if (name)
        {
-           strcat(buf, "  AND c.relname ~ '");
+           strcat(buf, "  AND c.relname ~ '^");
            strncat(buf, name, REGEXP_CUTOFF);
            strcat(buf, "'\n");
        }
@@ -997,7 +997,7 @@ listTables(const char *infotype, const char *name, bool desc)
        strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
        if (name)
        {
-           strcat(buf, "  AND c.relname ~ '");
+           strcat(buf, "  AND c.relname ~ '^");
            strncat(buf, name, REGEXP_CUTOFF);
            strcat(buf, "'\n");
        }
@@ -1013,7 +1013,7 @@ listTables(const char *infotype, const char *name, bool desc)
        strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
        if (name)
        {
-           strcat(buf, "  AND c.relname ~ '");
+           strcat(buf, "  AND c.relname ~ '^");
            strncat(buf, name, REGEXP_CUTOFF);
            strcat(buf, "'\n");
        }
@@ -1049,7 +1049,7 @@ listTables(const char *infotype, const char *name, bool desc)
        strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
        if (name)
        {
-           strcat(buf, "  AND c.relname ~ '");
+           strcat(buf, "  AND c.relname ~ '^");
            strncat(buf, name, REGEXP_CUTOFF);
            strcat(buf, "'\n");
        }
@@ -1079,7 +1079,7 @@ listTables(const char *infotype, const char *name, bool desc)
        strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
        if (name)
        {
-           strcat(buf, "  AND c.relname ~ '");
+           strcat(buf, "  AND c.relname ~ '^");
            strncat(buf, name, REGEXP_CUTOFF);
            strcat(buf, "'\n");
        }
@@ -1098,7 +1098,7 @@ listTables(const char *infotype, const char *name, bool desc)
               "WHERE c.relowner = u.usesysid AND c.relkind = 's'\n");
        if (name)
        {
-           strcat(buf, "  AND c.relname ~ '");
+           strcat(buf, "  AND c.relname ~ '^");
            strncat(buf, name, REGEXP_CUTOFF);
            strcat(buf, "'\n");
        }
@@ -1112,7 +1112,7 @@ listTables(const char *infotype, const char *name, bool desc)
           "  AND not exists (select 1 from pg_user where usesysid = c.relowner)");
        if (name)
        {
-           strcat(buf, "  AND c.relname ~ '");
+           strcat(buf, "  AND c.relname ~ '^");
            strncat(buf, name, REGEXP_CUTOFF);
            strcat(buf, "'\n");
        }
@@ -1127,10 +1127,10 @@ listTables(const char *infotype, const char *name, bool desc)
 
    if (PQntuples(res) == 0 && !QUIET())
     {
-   if (name)
-       fprintf(pset.queryFout, "No matching relations found.\n");
-   else
-       fprintf(pset.queryFout, "No relations found.\n");
+        if (name)
+            fprintf(pset.queryFout, "No matching relations found.\n");
+        else
+            fprintf(pset.queryFout, "No relations found.\n");
     }
    else
    {
index 70100c7791f6a2b6f111c87b0af65b90233e507d..261f134420364bbc1101c05fe9157f210a397e0b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/help.c,v 1.15 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/help.c,v 1.16 2000/02/07 23:10:06 petere Exp $
  */
 #include 
 #include "help.h"
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifndef WIN32
 #include          /* for ioctl() */
@@ -20,9 +21,7 @@
 #include          /* (ditto) */
 #include                 /* for getuid() */
 #else
-#define strcasecmp(x,y) stricmp(x,y)
-#define popen(x,y) _popen(x,y)
-#define pclose(x) _pclose(x)
+#include 
 #endif
 
 #include 
@@ -48,7 +47,6 @@ usage(void)
 
 #ifndef WIN32
    struct passwd *pw = NULL;
-
 #endif
 
    /* Find default user, in case we need it. */
@@ -61,7 +59,7 @@ usage(void)
            user = pw->pw_name;
        else
        {
-           perror("getpwuid()");
+           psql_error("could not get current user name: %s", strerror(errno));
            exit(EXIT_FAILURE);
        }
 #else
@@ -70,10 +68,11 @@ usage(void)
    }
 
 /* If this " is the start of the string then it ought to end there to fit in 80 columns >> " */
-    puts(  "This is psql, the PostgreSQL interactive terminal.");
-   puts(  "\nUsage:");
-    puts(  "  psql [options] [dbname [username]]");
-    puts(  "\nOptions:");
+    puts(  "This is psql, the PostgreSQL interactive terminal.\n");
+   puts(  "Usage:");
+    puts(  "  psql [options] [dbname [username]]\n");
+    puts(  "Options:");
+/* puts(  "  -a              Echo all input from script");*/
    puts(  "  -A              Unaligned table output mode (-P format=unaligned)");
    puts(  "  -c       Run only single query (or slash command) and exit");
 
@@ -83,7 +82,7 @@ usage(void)
        env = user;
    printf("  -d      Specify database name to connect to (default: %s)\n", env);
 
-   puts(  "  -e              Echo all input in non-interactive mode");
+    puts(  "  -e              Echo queries sent to backend");
    puts(  "  -E              Display queries that internal commands generate");
    puts(  "  -f    Execute queries from file, then exit");
    puts(  "  -F      Set field separator (default: \"" DEFAULT_FIELD_SEP "\") (-P fieldsep=)");
@@ -99,7 +98,6 @@ usage(void)
 
    puts(  "  -H              HTML table output mode (-P format=html)");
    puts(  "  -l              List available databases, then exit");
-   puts(  "  -n              Do not use readline or history");
    puts(  "  -o    Send query output to filename (or |pipe)");
 
    /* Display default port */
@@ -109,6 +107,7 @@ usage(void)
 
    puts(  "  -P var[=arg]    Set printing option 'var' to 'arg' (see \\pset command)");
    puts(  "  -q              Run quietly (no messages, only query output)");
+    puts(  "  -R      Set record separator (default: newline) (-P recordsep=)");
    puts(  "  -s              Single step mode (confirm each query)");
    puts(  "  -S              Single line mode (newline terminates query)");
    puts(  "  -t              Don't print headings and row count (-P tuples_only)");
@@ -118,7 +117,7 @@ usage(void)
    env = getenv("PGUSER");
    if (!env)
        env = user;
-   printf("  -U    Specifiy username, \"?\"=prompt (default user: %s)\n", env);
+   printf("  -U    Specify database username (default: %s)\n", env);
 
    puts(  "  -x              Turn on expanded table output (-P expanded)");
    puts(  "  -v name=val     Set psql variable 'name' to 'value'");
@@ -190,10 +189,9 @@ slashUsage(void)
        fout = stdout;
 
    /* if you add/remove a line here, change the row test above */
-   fprintf(fout, " \\?             help\n");
-   fprintf(fout, " \\c[onnect] [dbname|- [user|?]]\n"
+   fprintf(fout, " \\c[onnect] [dbname|- [user]]\n"
          "                 connect to new database (currently '%s')\n", PQdb(pset.db));
-   fprintf(fout, " \\copy ...      perform SQL COPY with data stream to the client machine");
+   fprintf(fout, " \\copy ...      perform SQL COPY with data stream to the client machine\n");
    fprintf(fout, " \\copyright     show PostgreSQL usage and distribution terms\n");
    fprintf(fout, " \\d      describe table (or view, index, sequence)\n");
    fprintf(fout, " \\d{i|s|t|v|S}  list only indices/sequences/tables/views/system tables\n");
@@ -209,10 +207,11 @@ slashUsage(void)
    fprintf(fout, " \\i      read and execute queries from filename\n");
    fprintf(fout, " \\l             list all databases\n");
    fprintf(fout, " \\lo_export, \\lo_import, \\lo_list, \\lo_unlink\n"
-         "                 large object operations\n");
+            "                  large object operations\n");
    fprintf(fout, " \\o [fname]     send all query results to , or |pipe\n");
    fprintf(fout, " \\p             show the content of the current query buffer\n");
-   fprintf(fout, " \\pset [opt]    set table output options\n");
+   fprintf(fout, " \\pset {format|border|expanded|fieldsep|recordsep|tuples_only|title|tableattr\n"
+            "     |pager}    set table output options\n");
    fprintf(fout, " \\q             quit psql\n");
    fprintf(fout, " \\qecho   write text to query output stream (see \\o)\n");
    fprintf(fout, " \\r             reset (clear) the query buffer\n");
@@ -243,36 +242,24 @@ slashUsage(void)
 void
 helpSQL(const char *topic)
 {
+#define VALUE_OR_NULL(a) ((a) ? (a) : "")
+
    if (!topic || strlen(topic) == 0)
    {
-       char        left_center_right;  /* Which column we're displaying */
-       int         i;          /* Index into QL_HELP[] */
+       int         i;
+        int         items_per_column = (QL_HELP_COUNT + 2)/3;
 
        puts("Available help:");
 
-       left_center_right = 'L';/* Start with left column */
-       i = 0;
-       while (QL_HELP[i].cmd != NULL)
+        for (i = 0; i < items_per_column; i++)
        {
-           switch (left_center_right)
-           {
-               case 'L':
-                   printf("    %-25s", QL_HELP[i].cmd);
-                   left_center_right = 'C';
-                   break;
-               case 'C':
-                   printf("%-25s", QL_HELP[i].cmd);
-                   left_center_right = 'R';
-                   break;
-               case 'R':
-                   printf("%-25s\n", QL_HELP[i].cmd);
-                   left_center_right = 'L';
-                   break;
-           }
-           i++;
+            printf("    %-25s%-25s%-25s\n",
+                   VALUE_OR_NULL(QL_HELP[i].cmd),
+                   VALUE_OR_NULL(QL_HELP[i + items_per_column].cmd),
+                   VALUE_OR_NULL(QL_HELP[i + 2*items_per_column].cmd)
+                   );
        }
-       if (left_center_right != 'L')
-           puts("\n");
+        putc('\n', stdout);
    }
 
    else
@@ -286,8 +273,10 @@ helpSQL(const char *topic)
                strcmp(topic, "*") == 0)
            {
                help_found = true;
-               printf("Command: %s\nDescription: %s\nSyntax:\n%s\n\n",
-                    QL_HELP[i].cmd, QL_HELP[i].help, QL_HELP[i].syntax);
+               printf("Command:     %s\n"
+                       "Description: %s\n"
+                       "Syntax:\n%s\n\n",
+                       QL_HELP[i].cmd, QL_HELP[i].help, QL_HELP[i].syntax);
            }
        }
 
@@ -298,28 +287,28 @@ helpSQL(const char *topic)
 
 
 
-
 void
 print_copyright(void)
 {
    puts(
-        "PostgreSQL Data Base Management System\n\n"
-    "Portions Copyright (c) 1996-2000, PostgreSQL, Inc\n\n"
-        "This software is based on Postgres95, formerly known as Postgres, which\n"
-        "contains the following notice:\n\n"
-    "Portions Copyright(c) 1994 - 7 Regents of the University of California\n\n"
-        "Permission to use, copy, modify, and distribute this software and its\n"
-        "documentation for any purpose, without fee, and without a written agreement\n"
-        "is hereby granted, provided that the above copyright notice and this paragraph\n"
-        "and the following two paragraphs appear in all copies.\n\n"
-        "IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\n"
-        "DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST\n"
-        "PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF\n"
-        "THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\n"
-        "DAMAGE.\n\n"
-        "THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\n"
-        "BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n"
-        "PARTICULAR PURPOSE.THE SOFTWARE PROVIDED HEREUNDER IS ON AN \"AS IS\" BASIS,\n"
-        "AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,\n"
-        "SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.");
+        "PostgreSQL Data Base Management System\n\n"
+        "Portions Copyright (c) 1996-2000, PostgreSQL, Inc\n\n"
+        "This software is based on Postgres95, formerly known as Postgres, which\n"
+        "contains the following notice:\n\n"
+        "Portions Copyright(c) 1994 - 7 Regents of the University of California\n\n"
+        "Permission to use, copy, modify, and distribute this software and its\n"
+        "documentation for any purpose, without fee, and without a written agreement\n"
+        "is hereby granted, provided that the above copyright notice and this paragraph\n"
+        "and the following two paragraphs appear in all copies.\n\n"
+        "IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\n"
+        "DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST\n"
+        "PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF\n"
+        "THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\n"
+        "DAMAGE.\n\n"
+        "THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\n"
+        "BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n"
+        "PARTICULAR PURPOSE.THE SOFTWARE PROVIDED HEREUNDER IS ON AN \"AS IS\" BASIS,\n"
+        "AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,\n"
+        "SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+        );
 }
index 2adff9d34224bfef6bef3888ac5dba355fe20c38..560d5b2c382fd2722d832a2ad58e40227aec16b2 100644 (file)
@@ -3,15 +3,18 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/input.c,v 1.8 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/input.c,v 1.9 2000/02/07 23:10:06 petere Exp $
  */
 #include 
 #include "input.h"
 
+#include 
+
 #include 
 
 #include "settings.h"
 #include "tab-complete.h"
+#include "common.h"
 
 /* Runtime options for turning off readline and history */
 /* (of course there is no runtime command for doing that :) */
@@ -32,7 +35,7 @@ static bool useHistory;
  * The result is malloced.
  */
 char *
-gets_interactive(const char *prompt)
+gets_interactive(char *prompt)
 {
    char       *s;
 #ifdef USE_HISTORY
@@ -42,7 +45,7 @@ gets_interactive(const char *prompt)
 
 #ifdef USE_READLINE
    if (useReadline)
-       s = readline((char *) prompt);
+       s = readline(prompt);
    else
    {
 #endif
@@ -120,7 +123,6 @@ initializeInput(int flags)
    if (flags == 1)
    {
        useReadline = true;
-       rl_readline_name = "psql";
         initialize_readline();
    }
 #endif
@@ -152,14 +154,14 @@ initializeInput(int flags)
 
 
 bool
-saveHistory(const char *fname)
+saveHistory(char *fname)
 {
 #ifdef USE_HISTORY
-   if (useHistory)
+   if (useHistory && fname)
    {
-       if (write_history((char *) fname) != 0)
+       if (write_history(fname) != 0)
        {
-           perror(fname);
+           psql_error("could not save history to %s: %s", fname, strerror(errno));
            return false;
        }
        return true;
index 6e078cbfbeaddfaa5b30ab345e569ba7917805bf..d12b45bfa3058bfcf19b47bd606ad5ff5e96184a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/input.h,v 1.6 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/input.h,v 1.7 2000/02/07 23:10:06 petere Exp $
  */
 #ifndef INPUT_H
 #define INPUT_H
 # endif
 #endif
 
-char * gets_interactive(const char *prompt);
+char * gets_interactive(char *prompt);
 char * gets_fromFile(FILE *source);
 
 void initializeInput(int flags);
-bool saveHistory(const char *fname);
+bool saveHistory(char *fname);
 void finishInput(void);
 
 #endif /* INPUT_H */
index 164956fded974257b78c728428b9f3720ffe8f17..add2f77cfc15fc4af5ef9e4519153da76137ffae 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.7 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.8 2000/02/07 23:10:06 petere Exp $
  */
 #include 
 #include "large_obj.h"
@@ -113,7 +113,7 @@ do_lo_export(const char *loid_arg, const char *filename_arg)
        PQclear(res);
    }
 
-   status = lo_export(pset.db, atol(loid_arg), (char *) filename_arg);
+   status = lo_export(pset.db, atol(loid_arg), filename_arg);
    if (status != 1)
    {                           /* of course this status is documented
                                 * nowhere :( */
@@ -182,7 +182,7 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
        PQclear(res);
    }
 
-   loid = lo_import(pset.db, (char *) filename_arg);
+   loid = lo_import(pset.db, filename_arg);
    if (loid == InvalidOid)
    {
        fputs(PQerrorMessage(pset.db), stderr);
index cf07b42d31fcfe1084068b745c5ba17a2ece4183..325a6b5ed85931b3b9eb8aba884c12494563a840 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.16 2000/01/24 19:34:17 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.17 2000/02/07 23:10:06 petere Exp $
  */
 #include 
 #include "mainloop.h"
@@ -47,10 +47,10 @@ MainLoop(FILE *source)
    bool        xcomment;       /* in extended comment */
    int         paren_level;
    unsigned int query_start;
-    int         count_eof;
+    int         count_eof = 0;
     const char *var;
     bool         was_bslash;
-    unsigned int bslash_count;
+    unsigned int bslash_count = 0;
 
    int         i,
                prevlen,
@@ -123,6 +123,8 @@ MainLoop(FILE *source)
                    prompt_status = PROMPT_DOUBLEQUOTE;
                else if (xcomment)
                    prompt_status = PROMPT_COMMENT;
+                else if (paren_level)
+                    prompt_status = PROMPT_PAREN;
                else if (query_buf->len > 0)
                    prompt_status = PROMPT_CONTINUE;
                else
@@ -251,7 +253,7 @@ MainLoop(FILE *source)
            }
 
            /* start of quote */
-           else if (line[i] == '\'' || line[i] == '"')
+           else if (!was_bslash && (line[i] == '\'' || line[i] == '"'))
                in_quote = line[i];
 
            /* in extended comment? */
index 3ff0d27c22777cb9e6ba7e61f2cf47ba6099702d..44faad5850fbd476afb173095377290dfb66c982 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/print.c,v 1.9 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/print.c,v 1.10 2000/02/07 23:10:06 petere Exp $
  */
 #include 
 #include "print.h"
@@ -266,7 +266,9 @@ print_aligned_text(const char *title, const char * const * headers,
        for (i = 0; i < col_count; i++)
        {
            /* centered */
-           fprintf(fout, "%-*s%s%-*s", (int) floor((widths[i] - strlen(headers[i])) / 2.0), "", headers[i], (int) ceil((widths[i] - strlen(headers[i])) / 2.0), "");
+           fprintf(fout, "%-*s%s%-*s",
+                    (int) floor((widths[i] - strlen(headers[i])) / 2.0), "",
+                    headers[i], (int) ceil((widths[i] - strlen(headers[i])) / 2.0), "");
 
            if (i < col_count - 1)
            {
index a06a712e401b6ef4c4bd80061499db36be85cbf9..1149fd65abcbcbc734dc00be68ff59ca3a752bd8 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.7 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.8 2000/02/07 23:10:06 petere Exp $
  */
 #include 
 #include "prompt.h"
@@ -19,8 +19,8 @@
 #include "variables.h"
 
 #ifdef WIN32
-#define popen(x,y) _popen(x,y)
-#define pclose(x) _pclose(x)
+#include 
+#include 
 #endif
 
 
  *
  * %`command`     - The result of executing command in /bin/sh with trailing
  *                  newline stripped.
- * %$name$        - The value of the psql variable 'name'
+ * %:name:        - The value of the psql variable 'name'
  * (those will not be rescanned for more escape sequences!)
  *
  * If the application-wide prompts became NULL somehow, the returned string
  * will be empty (not NULL!).
  *--------------------------
  */
-const char *
+char *
 get_prompt(promptStatus_t status)
 {
 #define MAX_PROMPT_SIZE 256
@@ -72,7 +72,7 @@ get_prompt(promptStatus_t status)
 
    if (status == PROMPT_READY)
        prompt_string = GetVariable(pset.vars, "PROMPT1");
-   else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status == PROMPT_COMMENT)
+   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");
@@ -183,6 +183,9 @@ get_prompt(promptStatus_t status)
                        case PROMPT_COMMENT:
                            buf[0] = '*';
                            break;
+                        case PROMPT_PAREN:
+                            buf[0] = '(';
+                            break;
                        default:
                            buf[0] = '\0';
                            break;
@@ -226,14 +229,14 @@ get_prompt(promptStatus_t status)
                    }
 
                    /* interpolate variable */
-               case '$':
+               case ':':
                    {
                        char       *name;
                        const char *val;
                        int         nameend;
 
                        name = strdup(p + 1);
-                       nameend = strcspn(name, "$");
+                       nameend = strcspn(name, ":");
                        name[nameend] = '\0';
                        val = GetVariable(pset.vars, name);
                        if (val)
index f70a334a54d03d41bd07ef2b391f14684e4a5782..61b4b9f543aabb63daafe94ab6b0dadf9e68f90d 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/prompt.h,v 1.5 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/prompt.h,v 1.6 2000/02/07 23:10:06 petere Exp $
  */
 #ifndef PROMPT_H
 #define PROMPT_H
@@ -17,9 +17,10 @@ typedef enum _promptStatus
    PROMPT_COMMENT,
    PROMPT_SINGLEQUOTE,
    PROMPT_DOUBLEQUOTE,
+    PROMPT_PAREN,
    PROMPT_COPY
 }          promptStatus_t;
 
-const char *get_prompt(promptStatus_t status);
+char *get_prompt(promptStatus_t status);
 
 #endif  /* PROMPT_H */
index 478356deb5536adb944b939ce73affb69486bac6..fa6e9fbf202f279d346bf16a03ebf1c7f6df99eb 100644 (file)
@@ -3,53 +3,48 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.21 2000/02/05 12:27:56 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.22 2000/02/07 23:10:06 petere Exp $
  */
 #include 
 
-#include 
-#include 
 #include 
 #include 
 #include 
 #include 
-#include 
 
-#ifdef WIN32
+#ifndef WIN32
+#include 
+#else /* WIN32 */
 #include 
 #include 
-#else
-#include 
-#endif
+#include 
+#endif /* WIN32 */
 
 #ifdef HAVE_GETOPT_H
 #include 
 #endif
 
 #include 
-#include 
 #include 
 
-#include "settings.h"
 #include "command.h"
-#include "help.h"
-#include "mainloop.h"
 #include "common.h"
+#include "describe.h"
+#include "help.h"
 #include "input.h"
-#include "variables.h"
+#include "mainloop.h"
 #include "print.h"
-#include "describe.h"
+#include "settings.h"
+#include "variables.h"
 
+/*
+ * Global psql options
+ */
 PsqlSettings pset;
 
-static void
-process_psqlrc(void);
 
-static void
-showVersion(void);
-
-
-/* Structures to pass information between the option parsing routine
+/*
+ * Structures to pass information between the option parsing routine
  * and the main function
  */
 enum _actions
@@ -75,15 +70,21 @@ struct adhoc_opts
 static void
 parse_options(int argc, char *argv[], struct adhoc_opts * options);
 
+static void
+process_psqlrc(void);
+
+static void
+showVersion(void);
+
 
 
 /*
  *
- * main()
+ * main
  *
  */
 int
-main(int argc, char **argv)
+main(int argc, char *argv[])
 {
    struct adhoc_opts options;
    int         successResult;
@@ -92,8 +93,6 @@ main(int argc, char **argv)
    char       *password = NULL;
    bool        need_pass;
 
-   memset(&pset, 0, sizeof pset);
-
     if (!strrchr(argv[0], SEP_CHAR))
         pset.progname = argv[0];
     else
@@ -104,21 +103,21 @@ main(int argc, char **argv)
     pset.encoding = PQenv2encoding();
 
    pset.vars = CreateVariableSpace();
+    if (!pset.vars)
+    {
+        fprintf(stderr, "%s: out of memory\n", pset.progname);
+        exit(EXIT_FAILURE);
+    }
    pset.popt.topt.format = PRINT_ALIGNED;
    pset.queryFout = stdout;
-   pset.popt.topt.fieldSep = xstrdup(DEFAULT_FIELD_SEP);
-   pset.popt.topt.recordSep = xstrdup(DEFAULT_RECORD_SEP);
    pset.popt.topt.border = 1;
    pset.popt.topt.pager = true;
 
-   SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
-   SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
-   SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
     SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
 
    pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
 
-   /* This is obsolete and will be removed very soon. */
+   /* This is obsolete and should be removed sometime. */
 #ifdef PSQL_ALWAYS_GET_PASSWORDS
    pset.getPassword = true;
 #else
@@ -127,11 +126,18 @@ main(int argc, char **argv)
 
    parse_options(argc, argv, &options);
 
-   if (options.action == ACT_LIST_DB)
-       options.dbname = "template1";
+    if (!pset.popt.topt.fieldSep)
+        pset.popt.topt.fieldSep = xstrdup(DEFAULT_FIELD_SEP);
+    if (!pset.popt.topt.recordSep)
+        pset.popt.topt.recordSep = xstrdup(DEFAULT_RECORD_SEP);
 
    if (options.username)
    {
+        /*
+         * The \001 is a hack to support the deprecated -u option which issues
+         * a username prompt. The recommended option is -U followed by the name
+         * on the command line.
+         */
        if (strcmp(options.username, "\001") == 0)
            username = simple_prompt("Username: ", 100, true);
        else
@@ -145,7 +151,9 @@ main(int argc, char **argv)
    do
    {
        need_pass = false;
-       pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.dbname, username, password);
+       pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL,
+                               options.action == ACT_LIST_DB ? "template1" : options.dbname,
+                               username, password);
 
        if (PQstatus(pset.db) == CONNECTION_BAD &&
            strcmp(PQerrorMessage(pset.db), "fe_sendauth: no password supplied\n") == 0)
@@ -162,8 +170,7 @@ main(int argc, char **argv)
 
    if (PQstatus(pset.db) == CONNECTION_BAD)
    {
-       fprintf(stderr, "%s: %s",
-                pset.progname, PQerrorMessage(pset.db));
+        fprintf(stderr, "%s: %s", pset.progname, PQerrorMessage(pset.db));
        PQfinish(pset.db);
        exit(EXIT_BADCONN);
    }
@@ -188,44 +195,62 @@ main(int argc, char **argv)
     SetVariable(pset.vars, "HOST", PQhost(pset.db));
     SetVariable(pset.vars, "PORT", PQport(pset.db));
 
-    pset.issuper = test_superuser(PQuser(pset.db));
-
-   if (!QUIET() && !pset.notty && !options.action)
-   {
-       printf("Welcome to %s, the PostgreSQL interactive terminal.\n\n"
-               "Type:  \\copyright for distribution terms\n"
-               "       \\h for help with SQL commands\n"
-               "       \\? for help on internal slash commands\n"
-               "       \\g or terminate with semicolon to execute query\n"
-               "       \\q to quit\n", pset.progname);
-   }
-
-   /* Now find something to do */
+   /*
+     * Now find something to do
+     */
 
-   /* process file given by -f */
+   /*
+     * process file given by -f
+     */
    if (options.action == ACT_FILE)
        successResult = process_file(options.action_string) ? 0 : 1;
-   /* process slash command if one was given to -c */
+   /*
+     * process slash command if one was given to -c
+     */
    else if (options.action == ACT_SINGLE_SLASH)
     {
-        if (GetVariable(pset.vars, "ECHO") && strcmp(GetVariable(pset.vars, "ECHO"), "full")==0)
+        const char * value;
+
+        if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "full")==0)
             puts(options.action_string);
        successResult = HandleSlashCmds(options.action_string, NULL, NULL) != CMD_ERROR ? 0 : 1;
     }
-   /* If the query given to -c was a normal one, send it */
+   /*
+     * If the query given to -c was a normal one, send it
+     */
    else if (options.action == ACT_SINGLE_QUERY)
     {
-        if (GetVariable(pset.vars, "ECHO") && strcmp(GetVariable(pset.vars, "ECHO"), "full")==0)
+        const char * value;
+
+        if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "full")==0)
             puts(options.action_string);
-       successResult = SendQuery( options.action_string) ? 0 : 1;
+       successResult = SendQuery(options.action_string) ? 0 : 1;
     }
-   /* or otherwise enter interactive main loop */
+   /*
+     * or otherwise enter interactive main loop
+     */
    else
     {
+        pset.issuper = test_superuser(PQuser(pset.db));
+        if (!QUIET() && !pset.notty)
+        {
+            printf("Welcome to %s, the PostgreSQL interactive terminal.\n\n"
+                   "Type:  \\copyright for distribution terms\n"
+                   "       \\h for help with SQL commands\n"
+                   "       \\? for help on internal slash commands\n"
+                   "       \\g or terminate with semicolon to execute query\n"
+                   "       \\q to quit\n\n", pset.progname);
+        }
+
+        SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
+        SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
+        SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
         process_psqlrc();
-        initializeInput(options.no_readline ? 0 : 1);
+        if (!pset.notty)
+            initializeInput(options.no_readline ? 0 : 1);
        successResult = MainLoop(stdin);
-        finishInput();
+        if (!pset.notty)
+            finishInput();
     }
 
    /* clean up */
@@ -253,7 +278,8 @@ static void
 parse_options(int argc, char *argv[], struct adhoc_opts * options)
 {
 #ifdef HAVE_GETOPT_LONG
-   static struct option long_options[] = {
+   static struct option long_options[] =
+    {
        {"no-align", no_argument, NULL, 'A'},
        {"command", required_argument, NULL, 'c'},
        {"dbname", required_argument, NULL, 'd'},
@@ -269,6 +295,7 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
        {"port", required_argument, NULL, 'p'},
        {"pset", required_argument, NULL, 'P'},
        {"quiet", no_argument, NULL, 'q'},
+        {"record-separator", required_argument, NULL, 'R'},
        {"single-step", no_argument, NULL, 's'},
        {"single-line", no_argument, NULL, 'S'},
        {"tuples-only", no_argument, NULL, 't'},
@@ -283,7 +310,7 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
    };
 
    int         optindex;
-#endif
+#endif /* HAVE_GETOPT_LONG */
 
    extern char *optarg;
    extern int  optind;
@@ -293,15 +320,15 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
    memset(options, 0, sizeof *options);
 
 #ifdef HAVE_GETOPT_LONG
-   while ((c = getopt_long(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qsStT:uU:v:VWx?", long_options, &optindex)) != -1)
-#else
+   while ((c = getopt_long(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qRsStT:uU:v:VWx?", long_options, &optindex)) != -1)
+#else /* not HAVE_GETOPT_LONG */
 
    /*
     * Be sure to leave the '-' in here, so we can catch accidental long
     * options.
     */
-   while ((c = getopt(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qsStT:uU:v:VWx?-")) != -1)
-#endif
+   while ((c = getopt(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qRsStT:uU:v:VWx?-")) != -1)
+#endif /* not HAVE_GETOPT_LONG */
    {
        switch (c)
        {
@@ -329,7 +356,7 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
                options->action_string = optarg;
                break;
            case 'F':
-               pset.popt.topt.fieldSep = strdup(optarg);
+               pset.popt.topt.fieldSep = xstrdup(optarg);
                break;
            case 'h':
                options->host = optarg;
@@ -377,6 +404,9 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
            case 'q':
                SetVariable(pset.vars, "QUIET", "");
                break;
+            case 'R':
+                pset.popt.topt.recordSep = xstrdup(optarg);
+                break;
            case 's':
                SetVariable(pset.vars, "SINGLESTEP", "");
                break;
@@ -507,7 +537,7 @@ process_psqlrc(void)
 
    if (home)
    {
-       psqlrc = (char *) malloc(strlen(home) + 20);
+       psqlrc = malloc(strlen(home) + 20);
        if (!psqlrc)
        {
             fprintf(stderr, "%s: out of memory\n", pset.progname);
@@ -570,7 +600,7 @@ showVersion(void)
 #endif
 
     puts("Portions Copyright (c) 1996-2000, PostgreSQL, Inc");
-    puts("Portions Copyright (C) 1996 Regents of the University of California");
+    puts("Portions Copyright (c) 1996 Regents of the University of California");
     puts("Read the file COPYRIGHT or use the command \\copyright to see the");
     puts("usage and distribution terms.");
 }
index 5ba48dc454c9edc03574a585b8a0ff812ae2f8b7..a0d3769fd231eded14dec29f66e7b22648b7c127 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/stringutils.c,v 1.23 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/stringutils.c,v 1.24 2000/02/07 23:10:06 petere Exp $
  */
 #include 
 #include "stringutils.h"
 #include 
 #include 
 #include 
-
 #include 
 
-#include 
-#ifndef HAVE_STRDUP
-#include 
-#endif
 #include 
 
 
 
-static void
-           unescape_quotes(char *source, char quote, char escape);
+static void unescape_quotes(char *source, int quote, int escape);
 
 
 /*
@@ -45,7 +39,7 @@ char *
 strtokx(const char *s,
        const char *delim,
        const char *quote,
-       char escape,
+       int escape,
        char *was_quoted,
        unsigned int *token_pos,
        int encoding)
@@ -60,6 +54,10 @@ strtokx(const char *s,
    char       *start;
    char       *cp = NULL;
 
+#ifndef MULTIBYTE
+    (void)encoding; /*not used*/
+#endif
+
    if (s)
    {
        free(storage);
@@ -160,7 +158,7 @@ strtokx(const char *s,
  * Resolves escaped quotes. Used by strtokx above.
  */
 static void
-unescape_quotes(char *source, char quote, char escape)
+unescape_quotes(char *source, int quote, int escape)
 {
    char       *p;
    char       *destination,
@@ -170,7 +168,7 @@ unescape_quotes(char *source, char quote, char escape)
    assert(source);
 #endif
 
-   destination = (char *) calloc(1, strlen(source) + 1);
+   destination = calloc(1, strlen(source) + 1);
    if (!destination)
    {
        perror("calloc");
index 914871d94eb36b7e98a30698524efda14942dd37..4201fd53001138aa36675e3421ae75f412ee3930 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/stringutils.h,v 1.13 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/stringutils.h,v 1.14 2000/02/07 23:10:07 petere Exp $
  */
 #ifndef STRINGUTILS_H
 #define STRINGUTILS_H
@@ -13,7 +13,7 @@
 extern char *strtokx(const char *s,
        const char *delim,
        const char *quote,
-       char escape,
+       int escape,
        char *was_quoted,
        unsigned int *token_pos,
        int encoding);
index 92112cead073c1ad5c8b05a274fb834ca88b8bea..50a15fc7d0b721ad17d92505b5b3482a2fdce90a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.9 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.10 2000/02/07 23:10:07 petere Exp $
  */
 
 /*-----------
@@ -121,9 +121,7 @@ pgsql_thing_t words_after_create[] = {
     { "TYPE",      "SELECT typname FROM pg_type WHERE substr(typname,1,%d)='%s'" },
     { "UNIQUE",    NULL }, /* for CREATE UNIQUE INDEX ... */
     { "USER",      "SELECT usename FROM pg_user WHERE substr(usename,1,%d)='%s'" },
-    { "VIEW",      NULL }, /* Telling a view from a table is not the easiest
-                 thing in the world, and the solutions I've seen
-                 don't really work, so I'll wait on this. */
+    { "VIEW",      "SELECT viewname FROM pg_views WHERE substr(viewname,1,%d)='%s'" },
     { NULL, NULL } /* end of list */
 };
 
index 96589497d30a1df78a07f1b2a8f599c69b54b73b..7a3bff45e9211e1febdf6c97568a3cda0a0b5d49 100644 (file)
@@ -10,7 +10,7 @@
  * exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.36 2000/01/26 05:58:45 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.37 2000/02/07 23:10:08 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -474,6 +474,10 @@ int
 fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
            const char *password, char *PQerrormsg)
 {
+#if !defined(KRB4) && !defined(KRB5)
+    (void)hostname; /*not used*/
+#endif
+
    switch (areq)
    {
            case AUTH_REQ_OK:
index 92d32917ef20baf836ca79a9bd8441a27623cddc..94bf6bf0b866fdfbb437c81bb9d3bdf063e2bf89 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.117 2000/02/05 12:33:22 ishii Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.118 2000/02/07 23:10:09 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2291,7 +2291,7 @@ conninfo_free()
 }
 
 /* =========== accessor functions for PGconn ========= */
-const char *
+char *
 PQdb(const PGconn *conn)
 {
    if (!conn)
@@ -2299,7 +2299,7 @@ PQdb(const PGconn *conn)
    return conn->dbName;
 }
 
-const char *
+char *
 PQuser(const PGconn *conn)
 {
    if (!conn)
@@ -2307,7 +2307,7 @@ PQuser(const PGconn *conn)
    return conn->pguser;
 }
 
-const char *
+char *
 PQpass(const PGconn *conn)
 {
    if (!conn)
@@ -2315,7 +2315,7 @@ PQpass(const PGconn *conn)
    return conn->pgpass;
 }
 
-const char *
+char *
 PQhost(const PGconn *conn)
 {
    if (!conn)
@@ -2323,7 +2323,7 @@ PQhost(const PGconn *conn)
    return conn->pghost;
 }
 
-const char *
+char *
 PQport(const PGconn *conn)
 {
    if (!conn)
@@ -2331,7 +2331,7 @@ PQport(const PGconn *conn)
    return conn->pgport;
 }
 
-const char *
+char *
 PQtty(const PGconn *conn)
 {
    if (!conn)
@@ -2339,7 +2339,7 @@ PQtty(const PGconn *conn)
    return conn->pgtty;
 }
 
-const char *
+char *
 PQoptions(const PGconn *conn)
 {
    if (!conn)
@@ -2355,7 +2355,7 @@ PQstatus(const PGconn *conn)
    return conn->status;
 }
 
-const char *
+char *
 PQerrorMessage(const PGconn *conn)
 {
    static char noConn[] = "PQerrorMessage: conn pointer is NULL\n";
@@ -2478,6 +2478,7 @@ PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
 static void
 defaultNoticeProcessor(void *arg, const char *message)
 {
+    (void)arg; /*not used*/
    /* Note: we expect the supplied string to end with a newline already. */
    fprintf(stderr, "%s", message);
 }
index 406ab4990307c8a49b8f0b816dce8e9e192e1482..8bba82e788ef224f02850a7ed3c43c390ce67ae5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.89 2000/01/26 05:58:45 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.90 2000/02/07 23:10:10 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,7 +27,7 @@
 #endif
 
 /* keep this in same order as ExecStatusType in libpq-fe.h */
-const char *const pgresStatus[] = {
+char * const pgresStatus[] = {
    "PGRES_EMPTY_QUERY",
    "PGRES_COMMAND_OK",
    "PGRES_TUPLES_OK",
@@ -1760,15 +1760,15 @@ PQresultStatus(const PGresult *res)
    return res->resultStatus;
 }
 
-const char *
+char *
 PQresStatus(ExecStatusType status)
 {
-   if ((int)status < 0 || (size_t)status >= sizeof pgresStatus / sizeof pgresStatus[0])
+   if (status < 0 || status >= sizeof pgresStatus / sizeof pgresStatus[0])
        return "Invalid ExecStatusType code";
    return pgresStatus[status];
 }
 
-const char *
+char *
 PQresultErrorMessage(const PGresult *res)
 {
    if (!res || !res->errMsg)
@@ -1862,7 +1862,7 @@ check_tuple_field_number(const char *routineName, const PGresult *res,
 /*
    returns NULL if the field_num is invalid
 */
-const char *
+char *
 PQfname(const PGresult *res, int field_num)
 {
    if (!check_field_number("PQfname", res, field_num))
@@ -1947,8 +1947,8 @@ PQfmod(const PGresult *res, int field_num)
        return 0;
 }
 
-const char *
-PQcmdStatus(const PGresult *res)
+char *
+PQcmdStatus(PGresult *res)
 {
    if (!res)
        return NULL;
@@ -1960,7 +1960,7 @@ PQcmdStatus(const PGresult *res)
    if the last command was an INSERT, return the oid string
    if not, return ""
 */
-const char *
+char *
 PQoidStatus(const PGresult *res)
 {
         /* 
@@ -2011,8 +2011,8 @@ PQoidValue(const PGresult *res)
    if the last command was an INSERT/UPDATE/DELETE, return number
    of inserted/affected tuples, if not, return ""
 */
-const char *
-PQcmdTuples(const PGresult *res)
+char *
+PQcmdTuples(PGresult *res)
 {
    char noticeBuf[128];
 
@@ -2023,7 +2023,7 @@ PQcmdTuples(const PGresult *res)
        strncmp(res->cmdStatus, "DELETE", 6) == 0 ||
        strncmp(res->cmdStatus, "UPDATE", 6) == 0)
    {
-       const char     *p = res->cmdStatus + 6;
+       char       *p = res->cmdStatus + 6;
 
        if (*p == 0)
        {
@@ -2067,7 +2067,7 @@ PQcmdTuples(const PGresult *res)
 
    if res is not binary, a null-terminated ASCII string is returned.
 */
-const char *
+char *
 PQgetvalue(const PGresult *res, int tup_num, int field_num)
 {
    if (!check_tuple_field_number("PQgetvalue", res, tup_num, field_num))
index e31b66a28b344095913a7fc35c17e41d0917d8f4..6a7fd71f440cb8ba961e8bc3a1498668cb711280 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.27 2000/01/26 05:58:45 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.28 2000/02/07 23:10:11 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -168,7 +168,7 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len)
  *
  */
 int
-lo_write(PGconn *conn, int fd, const char *buf, size_t len)
+lo_write(PGconn *conn, int fd, char *buf, size_t len)
 {
    PQArgBlock  argv[2];
    PGresult   *res;
index ff6acefea8f18294d6ccc8ab7b43c65cf0b0f318..d171c457d96558d4db0d01f1b6eefccdd80ae2cf 100644 (file)
@@ -25,7 +25,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.38 2000/01/29 16:58:51 petere Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.39 2000/02/07 23:10:11 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -782,6 +782,8 @@ PQenv2encoding(void)
 int
 PQmblen(const unsigned char *s, int encoding)
 {
+    (void)s;
+    (void)encoding;
    return 1;
 }
 int
index e54167cc1feef37a1dda2b2e6ba3741f4da41995..3b9102d4d8412797c6011588220cffbcc03e86bd 100644 (file)
@@ -10,7 +10,7 @@
  * didn't really belong there.
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-print.c,v 1.34 2000/02/05 12:33:22 ishii Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-print.c,v 1.35 2000/02/07 23:10:11 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -59,7 +59,7 @@ static char *do_header(FILE *fout, const PQprintOpt *po, const int nFields,
 static void output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
           unsigned char *fieldNotNum, int *fieldMax, char *border,
           const int row_index);
-
+static void fill(int length, int max, char filler, FILE *fp);
 
 /*
  * PQprint()
@@ -440,7 +440,6 @@ do_header(FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax,
        fputs("
", fout);
    else
    {
-       int         j;          /* for loop index */
        int         tot = 0;
        int         n = 0;
        char       *p = NULL;
@@ -557,7 +556,6 @@ output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
 
 
 
-#if 0
 /*
  * really old printing routines
  */
@@ -728,4 +726,17 @@ PQprintTuples(const PGresult *res,
        }
    }
 }
-#endif
+
+
+
+/* simply send out max-length number of filler characters to fp */
+static void
+fill(int length, int max, char filler, FILE *fp)
+{
+        int                     count;
+        count = max - length;
+        while (count-- >= 0)
+                putc(filler, fp);
+}
index 8acb622ad16f2481db9ed5d984d186a10d83883f..66437a903fd000852ab12e671b68717b0df0c0fa 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-fe.h,v 1.59 2000/02/05 12:33:22 ishii Exp $
+ * $Id: libpq-fe.h,v 1.60 2000/02/07 23:10:11 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -74,11 +74,6 @@ extern       "C"
        PGRES_FATAL_ERROR
    } ExecStatusType;
 
-/* String descriptions of the ExecStatusTypes.
- * NB: direct use of this array is now deprecated; call PQresStatus() instead.
- */
-   extern const char *const pgresStatus[];
-
 /* PGconn encapsulates a connection to the backend.
  * The contents of this struct are not supposed to be known to applications.
  */
@@ -115,16 +110,17 @@ extern        "C"
    typedef void (*PQnoticeProcessor) (void *arg, const char *message);
 
 /* Print options for PQprint() */
+    typedef char pqbool;
 
    typedef struct _PQprintOpt
    {
-       int         header;     /* print output field headings and row
+       pqbool      header;     /* print output field headings and row
                                 * count */
-       int         align;      /* fill align the fields */
-       int         standard;   /* old brain dead format */
-       int         html3;      /* output html tables */
-       int         expanded;   /* expand tables */
-       int         pager;      /* use pager for output if needed */
+       pqbool      align;      /* fill align the fields */
+       pqbool      standard;   /* old brain dead format */
+       pqbool      html3;      /* output html tables */
+       pqbool      expanded;   /* expand tables */
+       pqbool      pager;      /* use pager for output if needed */
        char       *fieldSep;   /* field separator */
        char       *tableOpt;   /* insert to HTML  */
        char       *caption;    /* HTML 
 */
@@ -207,15 +203,15 @@ extern        "C"
    extern int  PQrequestCancel(PGconn *conn);
 
    /* Accessor functions for PGconn objects */
-   extern const char *PQdb(const PGconn *conn);
-   extern const char *PQuser(const PGconn *conn);
-   extern const char *PQpass(const PGconn *conn);
-   extern const char *PQhost(const PGconn *conn);
-   extern const char *PQport(const PGconn *conn);
-   extern const char *PQtty(const PGconn *conn);
-   extern const char *PQoptions(const PGconn *conn);
+   extern char *PQdb(const PGconn *conn);
+   extern char *PQuser(const PGconn *conn);
+   extern char *PQpass(const PGconn *conn);
+   extern char *PQhost(const PGconn *conn);
+   extern char *PQport(const PGconn *conn);
+   extern char *PQtty(const PGconn *conn);
+   extern char *PQoptions(const PGconn *conn);
    extern ConnStatusType PQstatus(const PGconn *conn);
-   extern const char *PQerrorMessage(const PGconn *conn);
+   extern char *PQerrorMessage(const PGconn *conn);
    extern int  PQsocket(const PGconn *conn);
    extern int  PQbackendPID(const PGconn *conn);
    extern int  PQclientEncoding(const PGconn *conn);
@@ -279,21 +275,21 @@ extern        "C"
 
    /* Accessor functions for PGresult objects */
    extern ExecStatusType PQresultStatus(const PGresult *res);
-   extern const char *PQresStatus(ExecStatusType status);
-   extern const char *PQresultErrorMessage(const PGresult *res);
+   extern char *PQresStatus(ExecStatusType status);
+   extern char *PQresultErrorMessage(const PGresult *res);
    extern int  PQntuples(const PGresult *res);
    extern int  PQnfields(const PGresult *res);
    extern int  PQbinaryTuples(const PGresult *res);
-   extern const char *PQfname(const PGresult *res, int field_num);
+   extern char *PQfname(const PGresult *res, int field_num);
    extern int  PQfnumber(const PGresult *res, const char *field_name);
    extern Oid  PQftype(const PGresult *res, int field_num);
    extern int  PQfsize(const PGresult *res, int field_num);
    extern int  PQfmod(const PGresult *res, int field_num);
-   extern const char *PQcmdStatus(const PGresult *res);
-    extern const char *PQoidStatus(const PGresult *res); /* old and ugly */
+   extern char *PQcmdStatus(PGresult *res);
+    extern char *PQoidStatus(const PGresult *res); /* old and ugly */
     extern Oid PQoidValue(const PGresult *res); /* new and improved */
-   extern const char *PQcmdTuples(const PGresult *res);
-   extern const char *PQgetvalue(const PGresult *res, int tup_num, int field_num);
+   extern char *PQcmdTuples(PGresult *res);
+   extern char *PQgetvalue(const PGresult *res, int tup_num, int field_num);
    extern int  PQgetlength(const PGresult *res, int tup_num, int field_num);
    extern int  PQgetisnull(const PGresult *res, int tup_num, int field_num);
 
@@ -313,7 +309,6 @@ extern      "C"
                const PGresult *res,
                const PQprintOpt *ps);  /* option structure */
 
-#if 0
     /*
      * really old printing routines
      */
@@ -330,7 +325,7 @@ extern      "C"
                               int terseOutput,      /* delimiter bars */
                               int width);   /* width of column, if
                                              * 0, use variable width */
-#endif
+
 
 /* === in fe-lobj.c === */
 
@@ -338,7 +333,7 @@ extern      "C"
    extern int  lo_open(PGconn *conn, Oid lobjId, int mode);
    extern int  lo_close(PGconn *conn, int fd);
    extern int  lo_read(PGconn *conn, int fd, char *buf, size_t len);
-   extern int  lo_write(PGconn *conn, int fd, const char *buf, size_t len);
+   extern int  lo_write(PGconn *conn, int fd, char *buf, size_t len);
    extern int  lo_lseek(PGconn *conn, int fd, int offset, int whence);
    extern Oid  lo_creat(PGconn *conn, int mode);
    extern int  lo_tell(PGconn *conn, int fd);
index bb6f193bfe8d1aed459db572ac5245c701218308..16555d98852e275d30cc8076e7a00481fe60db54 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-int.h,v 1.18 2000/01/26 05:58:46 momjian Exp $
+ * $Id: libpq-int.h,v 1.19 2000/02/07 23:10:11 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -244,6 +244,11 @@ struct pg_conn
    int client_encoding;        /* encoding id */
 };
 
+/* String descriptions of the ExecStatusTypes.
+ * direct use of this array is deprecated; call PQresStatus() instead.
+ */
+extern char *const pgresStatus[];
+
 /* ----------------
  * Internal functions of libpq
  * Functions declared here need to be visible across files of libpq,
index dc006e55c8ecc258101469e7f462adedfa30e172..f70d9139c2ed7add9f5600492130a820f2f70a0a 100644 (file)
@@ -17,7 +17,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.4 2000/01/26 05:58:46 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.5 2000/02/07 23:10:11 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -124,9 +124,9 @@ resetPQExpBuffer(PQExpBuffer str)
  * Returns 1 if OK, 0 if failed to enlarge buffer.
  */
 int
-enlargePQExpBuffer(PQExpBuffer str, int needed)
+enlargePQExpBuffer(PQExpBuffer str, size_t needed)
 {
-   int         newlen;
+   size_t      newlen;
    char       *newdata;
 
    needed += str->len + 1;     /* total space required now */
@@ -164,8 +164,8 @@ void
 printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
 {
    va_list     args;
-   int         avail,
-               nprinted;
+   size_t      avail;
+    int         nprinted;
 
    resetPQExpBuffer(str);
 
@@ -214,8 +214,8 @@ void
 appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
 {
    va_list     args;
-   int         avail,
-               nprinted;
+   size_t      avail;
+    int            nprinted;
 
    for (;;)
    {
@@ -286,7 +286,7 @@ appendPQExpBufferChar(PQExpBuffer str, char ch)
  * if necessary.
  */
 void
-appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, int datalen)
+appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, size_t datalen)
 {
    /* Make more room if needed */
    if (! enlargePQExpBuffer(str, datalen))
index b70170d61a5de3f160bbca7b61a0715f7d067741..014254465aa78496850b96db5dd4a8d3fae74c1c 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pqexpbuffer.h,v 1.3 2000/01/26 05:58:46 momjian Exp $
+ * $Id: pqexpbuffer.h,v 1.4 2000/02/07 23:10:11 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,8 +40,8 @@
 typedef struct PQExpBufferData
 {
    char       *data;
-   int         len;
-   int         maxlen;
+   size_t      len;
+   size_t      maxlen;
 } PQExpBufferData;
 
 typedef PQExpBufferData *PQExpBuffer;
@@ -113,7 +113,7 @@ extern void resetPQExpBuffer(PQExpBuffer str);
  *
  * Returns 1 if OK, 0 if failed to enlarge buffer.
  */
-extern int enlargePQExpBuffer(PQExpBuffer str, int needed);
+extern int enlargePQExpBuffer(PQExpBuffer str, size_t needed);
 
 /*------------------------
  * printfPQExpBuffer
@@ -153,6 +153,6 @@ extern void appendPQExpBufferChar(PQExpBuffer str, char ch);
  * if necessary.
  */
 extern void appendBinaryPQExpBuffer(PQExpBuffer str,
-                      const char *data, int datalen);
+                      const char *data, size_t datalen);
 
 #endif  /* PQEXPBUFFER_H */
index 6988bcd98fe599c66153a2c3280ea681c78edaa7..91f7df1a2d372fbce1bb6c9892bd0acbe2fad23a 100644 (file)
  * Some compat functions
  */
 #define open(a,b,c) _open(a,b,c)
+#define close(a) _close(a)
 #define read(a,b,c) _read(a,b,c)
 #define write(a,b,c) _write(a,b,c)
-
+#define popen(a,b) _popen(a,b)
+#define pclose(a) _pclose(a)
 
 /*
  * crypt not available (yet)