OSDN Git Service

Fixed psql double quoting of SQL ids
authorPeter Eisentraut <peter_e@gmx.net>
Mon, 7 Feb 2000 23:10:11 +0000 (23:10 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
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 46e90bb..964dde8 100644 (file)
@@ -494,7 +494,7 @@ soon.)
 <function>PQdb</function>  
          Returns the database name of the connection.
 <synopsis>
-const char *PQdb(const PGconn *conn)
+char *PQdb(const PGconn *conn)
 </synopsis>
 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.
 <function>PQuser</function>
          Returns the user name of the connection.
 <synopsis>
-const char *PQuser(const PGconn *conn)
+char *PQuser(const PGconn *conn)
 </synopsis>
 </para>
 </listitem>
@@ -517,7 +517,7 @@ const char *PQuser(const PGconn *conn)
 <function>PQpass</function>
          Returns the password of the connection.
 <synopsis>
-const char *PQpass(const PGconn *conn)
+char *PQpass(const PGconn *conn)
 </synopsis>
 </para>
 </listitem>
@@ -527,7 +527,7 @@ const char *PQpass(const PGconn *conn)
 <function>PQhost</function>
          Returns the server host name of the connection.
 <synopsis>
-const char *PQhost(const PGconn *conn)
+char *PQhost(const PGconn *conn)
 </synopsis>
 </para>
 </listitem>
@@ -537,7 +537,7 @@ const char *PQhost(const PGconn *conn)
 <function>PQport</function>
          Returns the port of the connection.
 <synopsis>
-const char *PQport(const PGconn *conn)
+char *PQport(const PGconn *conn)
 </synopsis>
 </para>
 </listitem>
@@ -547,7 +547,7 @@ const char *PQport(const PGconn *conn)
 <function>PQtty</function>
          Returns the debug tty of the connection.
 <synopsis>
-const char *PQtty(const PGconn *conn)
+char *PQtty(const PGconn *conn)
 </synopsis>
 </para>
 </listitem>
@@ -557,7 +557,7 @@ const char *PQtty(const PGconn *conn)
 <function>PQoptions</function>
        Returns the backend options used in  the  connection.
 <synopsis>
-const char *PQoptions(const PGconn *conn)
+char *PQoptions(const PGconn *conn)
 </synopsis>
 </para>
 </listitem>
@@ -602,7 +602,7 @@ ConnStatusType PQstatus(const PGconn *conn)
        Returns the error message most recently generated by
        an operation on the connection.
        <synopsis>
-const char *PQerrorMessage(const PGconn* conn);
+char *PQerrorMessage(const PGconn* conn);
        </synopsis>
       </para>
 
@@ -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.
 <synopsis>
-const char *PQresStatus(ExecStatusType status);
+char *PQresStatus(ExecStatusType status);
 </synopsis>
 </para>
 </listitem>
@@ -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.
 <synopsis>
-const char *PQresultErrorMessage(const PGresult *res);
+char *PQresultErrorMessage(const PGresult *res);
 </synopsis>
 Immediately following a <function>PQexec</function> or <function>PQgetResult</function>
 call, <function>PQerrorMessage</function> (on the connection) will return the same
@@ -855,7 +855,7 @@ extracts data from a <acronym>BINARY</acronym> cursor.
  Returns the field (attribute) name associated with the given field  index.
  Field  indices start at 0.
 <synopsis>
-const char *PQfname(const PGresult *res,
+char *PQfname(const PGresult *res,
                     int field_index);
 </synopsis>
 </para>
@@ -931,9 +931,9 @@ int PQfmod(const PGresult *res,
            of a PGresult.
            Tuple and field indices start at 0.
 <synopsis>
-const char* PQgetvalue(const PGresult *res,
-                       int tup_num,
-                       int field_num);
+char* PQgetvalue(const PGresult *res,
+                 int tup_num,
+                 int field_num);
 </synopsis>
 For most queries, the value returned by <function>PQgetvalue</function>
 is a null-terminated <acronym>ASCII</acronym> string  representation
@@ -991,7 +991,7 @@ int PQgetisnull(const PGresult *res,
           Returns the command status string from the SQL command that
          generated the PGresult.
 <synopsis>
-const char * PQcmdStatus(const PGresult *res);
+char * PQcmdStatus(const PGresult *res);
 </synopsis>
 </para>
 </listitem>
@@ -1001,7 +1001,7 @@ const char * PQcmdStatus(const PGresult *res);
 <function>PQcmdTuples</function>
          Returns the number of rows affected by the SQL command.
 <synopsis>
-const char * PQcmdTuples(const PGresult *res);
+char * PQcmdTuples(const PGresult *res);
 </synopsis>
           If the <acronym>SQL</acronym> 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 <acronym>SQL</acronym> command was an INSERT.
           Otherwise, returns an empty string.
 <synopsis>
-const char * PQoidStatus(const PGresult *res);
+char * PQoidStatus(const PGresult *res);
 </synopsis>
 The function is deprecated in favor of <function>PQoidValue</function>
 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 &lt;table ...&gt; */
     char    *caption;    /* HTML &lt;caption&gt; */
     char    **fieldName; /* null terminated array of replacement field names */
 } PQprintOpt;
 </synopsis>
-
 This function was formerly used by <application>psql</application>
 to print query results, but this is no longer the case and this
-function is no longer supported.
+function is no longer actively supported.
 </para>
 </listitem>
 
+</listitem>
 <listitem>
 <para>
 <function>PQclear</function>
index 8f68d7e..4d0bf42 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.22 2000/01/29 16:58:27 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.23 2000/02/07 23:10:03 petere Exp $
 Postgres documentation
 -->
 
@@ -64,8 +64,8 @@ Postgres documentation
 
     <para>
     <application>psql</application> is a regular <productname>PostgreSQL</productname>
-    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. <application>psql</application> can be
     told about those parameters via command line options, namely <option>-d</option>,
     <option>-h</option>, <option>-p</option>, and <option>-U</option> 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.
     </para>
 
     <para>
@@ -155,31 +155,35 @@ testdb=>
     </para>
 
     <para>
-    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 <literal>\n</literal> (new line), <literal>\t</literal> (tab),
-    <literal>\</literal><replaceable>digits</replaceable>,
+    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 <literal>\n</literal> (new line), <literal>\t</literal>
+     (tab), <literal>\</literal><replaceable>digits</replaceable>,
     <literal>\0</literal><replaceable>digits</replaceable>, and
     <literal>\0x</literal><replaceable>digits</replaceable>
     (the character with the given decimal, octal, or hexadecimal code).
     </para>
 
     <para>
-    If an unquoted argument begins with a dollar sign (<literal>$</literal>),
+    If an unquoted argument begins with a colon (<literal>:</literal>),
     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 <literal>${...}</literal> sequence. See also under
-    <quote><xref linkend="APP-PSQL-variables" endterm="APP-PSQL-variables-title"></quote>.
+    argument instead.
     </para>
 
     <para>
-    Arguments that are quoted in <quote>back-ticks</quote> (<literal>`</literal>)
-    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 <quote>backticks</quote> (<literal>`</literal>)
+    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.
+    </para>
+
+    <para>
+    Some commands take the name of an <acronym>SQL</acronym> identifier (such as
+    a table name) as argument. These arguments follow the syntax rules of
+    <acronym>SQL</acronym> 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.
     </para>
 
     <para>
@@ -189,7 +193,7 @@ testdb=>
     (two backslashes) marks the end of arguments and continues parsing
     <acronym>SQL</acronym> queries, if any. That way <acronym>SQL</acronym> and
     <application>psql</application> 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. 
     </para>
 
@@ -246,7 +250,7 @@ testdb=>
 
        <para>
        If the connection attempt failed (wrong username, access denied, etc.) the
-       previous connection will be kept, if and only if <application>psql</application> is
+       previous connection will be kept if and only if <application>psql</application> 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=>
         <para>
        This operation is not as efficient as the <acronym>SQL</acronym> 
        <command>COPY</command> 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.
         </para>
         </tip>
@@ -510,12 +514,15 @@ testdb=>
         <term><literal>\echo</literal> <replaceable class="parameter">text</replaceable> [ ... ]</term>
         <listitem>
        <para>
-        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:
 <programlisting>
 => <userinput>\echo `date`</userinput>
 Tue Oct 26 21:40:57 CEST 1999
 </programlisting>
+        If the first argument is an unquoted <literal>-n</literal> the the trailing
+        newline is not written.
        </para>
 
        <tip>
@@ -602,7 +609,7 @@ Tue Oct 26 21:40:57 CEST 1999
        <note>
        <para>
        If you want to see the lines on the screen as they are read you must set
-       the variable <envar>echo</envar>.
+       the variable <envar>ECHO</envar> to <literal>full</literal>.
        </para>
        </note>
         </listitem>
@@ -658,7 +665,7 @@ Tue Oct 26 21:40:57 CEST 1999
        Stores the file into a <productname>PostgreSQL</productname> <quote>large object</quote>.
        Optionally, it associates the given comment with the object. Example:
 <programlisting>
-foo=> <userinput>\lo_import '/home/me/pictures/photo.xcf' 'a picture of me'</userinput>
+foo=> <userinput>\lo_import '/home/peter/pictures/photo.xcf' 'a picture of me'</userinput>
 lo_import 152801
 </programlisting>
        The response indicates that the large object received object id 152801
@@ -1006,12 +1013,13 @@ lo_import 152801
 
 
       <varlistentry>
-        <term><literal>\set</literal> [ <replaceable class="parameter">name</replaceable> [ <replaceable class="parameter">value</replaceable> ]]</term>
+        <term><literal>\set</literal> [ <replaceable class="parameter">name</replaceable> [ <replaceable class="parameter">value</replaceable> [ ... ]]]</term>
 
        <listitem>
        <para>
        Sets the internal variable <replaceable class="parameter">name</replaceable>
-       to <replaceable class="parameter">value</replaceable>. If no second argument
+       to <replaceable class="parameter">value</replaceable> 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 <command>\unset</command> command.
        </para>
@@ -1145,9 +1153,7 @@ Access permissions for database "test"
         <para>
         Escapes to a separate Unix shell or executes the Unix command
         <replaceable class="parameter">command</replaceable>. 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 <application>psql</application>'s
-        variable substitution features, use the backticks (<literal>`</literal>).
+        are not further interpreted, the shell will see them as is.
         </para>
         </listitem>
       </varlistentry>
@@ -1200,7 +1206,7 @@ Access permissions for database "test"
       <para>
       Specifies that <application>psql</application>
       is to execute one query string, <replaceable class="parameter">query</replaceable>,
-      and then exit.  This is useful for shell scripts.
+      and then exit.  This is useful in shell scripts.
       </para>
       <para>
       <replaceable class="parameter">query</replaceable> 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 <acronym>SQL</acronym> and <application>psql</application>
       meta-commands. To achieve this you could pipe the string into
-      <application>psql</application> and finish it with a a <literal>\q</literal>,
-      like so: <literal>echo "select * from foo; \q" | psql</literal>.
+      <application>psql</application>, like so:
+      <literal>echo "\x \\ select * from foo;" | psql</literal>.
       </para>
       </listitem>
     </varlistentry>
@@ -1260,6 +1266,16 @@ Access permissions for database "test"
       After the file is processed, <application>psql</application> terminates.
       This in many ways equivalent to the internal command <command>\i</command>.
       </para>
+      <para>
+      Using this option is subtly different from writing
+      <literal>psql &lt; <replaceable class="parameter">filename</replaceable></literal>.
+      In general, both will do what you expect, but using <literal>-f</literal>
+      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.
+      </para>
       </listitem>
     </varlistentry>
 
@@ -1312,16 +1328,6 @@ Access permissions for database "test"
 
 
     <varlistentry>
-      <term>-n, --no-readline</term>
-      <listitem>
-      <para>
-      Do not use readline for line editing and do not use the history.
-      </para>
-      </listitem>
-    </varlistentry>
-
-
-    <varlistentry>
       <term>-o, --output <replaceable class="parameter">filename</replaceable></term>
       <listitem>
       <para>
@@ -1372,6 +1378,17 @@ Access permissions for database "test"
       </listitem>
     </varlistentry>
 
+
+    <varlistentry>
+      <term>-R, --record-separator <replaceable class="parameter">separator</replaceable></term>
+      <listitem>
+      <para>
+      Use <replaceable class="parameter">separator</replaceable> as the record separator.
+      This is equivalent to the <command>\pset recordsep</command> command.
+      </para>
+      </listitem>
+    </varlistentry>
+
  
     <varlistentry>
       <term>-s, --single-step</term>
@@ -1492,7 +1509,7 @@ Access permissions for database "test"
       <para>
       As of version 7.0, <application>psql</application> automatically issues a
       password prompt whenever the backend requests password authentication.
-      Because this is currently based on a <quote>hack</quote> the automatic
+      Because this is currently based on a <quote>hack</quote>, 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"
 
     <para>
     <application>psql</application> 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 <application>psql</application> meta-command <command>\set</command>:
 <programlisting>
 testdb=> <userinput>\set foo bar</userinput>
 </programlisting>
     sets the variable <quote>foo</quote> to the value <quote>bar</quote>. 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:
 <programlisting>
-testdb=> <userinput>\echo $foo</userinput>
+testdb=> <userinput>\echo :foo</userinput>
 bar
 </programlisting>
-    Alternatively, the value can also be interpolated into a double-quoted (or backtick-quoted)
-    string, like so:
-<programlisting>
-testdb=> <userinput>\echo "foo is now ${foo}."</userinput>
-foo is now bar.
-</programlisting>
-    (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., <command>\copy</command>).
     </para>
 
     <note>
     <para>
     The arguments of <command>\set</command> are subject to the same substitution
     rules as with other commands. Thus you can construct interesting references
-    such as <literal>\set "${foo}bar" 'something'</literal> and get <quote>soft
+    such as <literal>\set :foo 'something'</literal> and get <quote>soft
     links</quote> or <quote>variable variables</quote> of <productname>Perl</productname>
     or <productname><acronym>PHP</acronym></productname> fame, respectively.
     Unfortunately (or fortunately?), there is not way to do anything useful
-    with these constructs. (<literal>\echo ${${foo}}</literal> doesn't work.) On the
-    other hand, <literal>\set bar $foo</literal> is a perfectly valid way to copy
+    with these constructs. On the
+    other hand, <literal>\set bar :foo</literal> is a perfectly valid way to copy
     a variable.
     </para>
     </note>
 
     <para>
-    If you call <command>\set</command> without an argument, the variable is simply
+    If you call <command>\set</command> without a second argument, the variable is simply
     set, but has no value. To unset (or delete) a variable, use the command
     <command>\unset</command>.
     </para>
@@ -1830,7 +1840,7 @@ foo is now bar.
     <para>
     An additional useful feature of <application>psql</application> variables
     is that you can substitute (<quote>interpolate</quote>) them into
-    regular <acronym>SQL</acronym> statements. The syntax for this is to prepend
+    regular <acronym>SQL</acronym> statements. The syntax for this is again to prepend
     the variable name with a colon (<literal>:</literal>).
 <programlisting>
 testdb=> <userinput>\set foo 'my_table'</userinput>
@@ -1850,8 +1860,7 @@ testdb=> <userinput>SELECT * FROM :foo;</userinput>
     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.
 <programlisting>
-testdb=> <userinput>\set content `cat my_file.txt`</userinput>
-testdb=> <userinput>\set content "'${content}'"</userinput>
+testdb=> <userinput>\set content '\'' `cat my_file.txt` '\''</userinput>
 testdb=> <userinput>INSERT INTO my_table VALUES (:content);</userinput>
 </programlisting>
     One possible problem with this approach is that <filename>my_file.txt</filename>
@@ -1877,11 +1886,12 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
 
     <para>
     Since colons may legally appear in queries, the following rule applies: If the variable
-    is not set, the character sequence <quote>colon-name</quote> is not changed. In any
+    is not set, the character sequence <quote>colon name</quote> 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 <acronym>SQL</acronym> for embedded
     query languages, such as <application>ecpg</application>. The colon syntax for
-    array slices and type casts are <productname>PostgreSQL</productname> extensions.)
+    array slices and type casts are <productname>PostgreSQL</productname> extensions,
+    hence the conflict.)
     </para>
 
   </refsect2>
@@ -1975,7 +1985,7 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
       </varlistentry>
 
       <varlistentry>
-        <term><literal>%$</literal><replaceable class="parameter">name</replaceable><literal>$</literal></term>
+        <term><literal>%:</literal><replaceable class="parameter">name</replaceable><literal>:</literal></term>
        <listitem><para>
        The value of the <application>psql</application>, <quote>magic</quote>, or environment
        variable <replaceable class="parameter">name</replaceable>. See the section
@@ -2032,13 +2042,22 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
 
     <para>
     <application>psql</application> 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 <filename>.psql_history</filename> in your home directory and is reloaded when
     <application>psql</application> starts up.
     Tab-completion is also supported, although
     the completion logic makes no claim to be an <acronym>SQL</acronym> parser.
     When available, <application>psql</application> 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 <filename>.inputrc</filename> in your
+    home directory:
+<programlisting>
+$if psql
+set disable-completion on
+$endif
+</programlisting>
+    (This is not a <application>psql</application> but a <application>readline</application>
+    feature. Read its documentation for further details.)
     </para>
 
     <para>
@@ -2053,7 +2072,7 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
     you have the library and header files installed in an obscure place you
     must tell <filename>configure</filename> about them, for example:
 <programlisting>
-$ ./configure --with-includes=/opt/gnu/include --with-libraries=/opt/gnu/lib  ...
+$ ./configure --with-includes=/opt/gnu/include --with-libs=/opt/gnu/lib  ...
 </programlisting>
     Then you have to recompile <application>psql</application> (not necessarily
     the entire code tree).
@@ -2105,7 +2124,7 @@ testdb=> <userinput>\d my_table</userinput>
   At this point you decide to change the prompt to something more
   interesting:
 <programlisting>
-testdb=> <userinput>\set prompt1 '%n@%m %~%R%# '</userinput>
+testdb=> <userinput>\set PROMPT1 '%n@%m %~%R%# '</userinput>
 peter@localhost testdb=>
 </programlisting>
   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".
       </para>
       </listitem>
 
-      <listitem>
-      <para>
-      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.
-      </para>
-      </listitem>
     </itemizedlist>
 
   </refsect2>
index 63ac6fb..ba198d7 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 <c.h>
 #include "command.h"
 
 #include <errno.h>
+#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>                 /* for umask() */
 #include <sys/stat.h>                  /* for umask(), stat() */
 #include <unistd.h>                            /* for geteuid(), getpid(), stat() */
+#else
+#include <win32.h>
 #endif
-#include <assert.h>
 
 #include <libpq-fe.h>
 #include <pqexpbuffer.h>
 
-#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", "\"'`", '\\', &quote, &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", "\"'`", '\\', &quote, &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, &quoted)))
+        {
+            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 <table ...> 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 700542c..084d879 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 <c.h>
 #include "common.h"
@@ -24,6 +24,7 @@
 #include <unistd.h>                            /* for write() */
 #else
 #include <io.h>                 /* for _write() */
+#include <win32.h>
 #endif
 
 #include <libpq-fe.h>
 #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 f802d5e..638b966 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 bb259b3..6ab7c2f 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 <c.h>
 #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 70100c7..261f134 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 <c.h>
 #include "help.h"
@@ -11,6 +11,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <errno.h>
 
 #ifndef WIN32
 #include <sys/ioctl.h>                 /* for ioctl() */
@@ -20,9 +21,7 @@
 #include <sys/types.h>                 /* (ditto) */
 #include <unistd.h>                            /* for getuid() */
 #else
-#define strcasecmp(x,y) stricmp(x,y)
-#define popen(x,y) _popen(x,y)
-#define pclose(x) _pclose(x)
+#include <win32.h>
 #endif
 
 #include <pqsignal.h>
@@ -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 <query>      Run only single query (or slash command) and exit");
 
@@ -83,7 +82,7 @@ usage(void)
                env = user;
        printf("  -d <dbname>     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 <filename>   Execute queries from file, then exit");
        puts(  "  -F <string>     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 <filename>   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 <string>     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 <username>   Specifiy username, \"?\"=prompt (default user: %s)\n", env);
+       printf("  -U <username>   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 <table>     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 <fname>     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 <fname>, 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 <text>  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 2adff9d..560d5b2 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 <c.h>
 #include "input.h"
 
+#include <errno.h>
+
 #include <pqexpbuffer.h>
 
 #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 6e078cb..d12b45b 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 164956f..add2f77 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 <c.h>
 #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 cf07b42..325a6b5 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 <c.h>
 #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 3ff0d27..44faad5 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 <c.h>
 #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 a06a712..1149fd6 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 <c.h>
 #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 <io.h>
+#include <win32.h>
 #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 f70a334..61b4b9f 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 478356d..fa6e9fb 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 <c.h>
 
-#include <signal.h>
-#include <errno.h>
 #include <sys/types.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
-#include <assert.h>
 
-#ifdef WIN32
+#ifndef WIN32
+#include <unistd.h>
+#else /* WIN32 */
 #include <io.h>
 #include <windows.h>
-#else
-#include <unistd.h>
-#endif
+#include <win32.h>
+#endif /* WIN32 */
 
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
 #endif
 
 #include <libpq-fe.h>
-#include <pqsignal.h>
 #include <version.h>
 
-#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 5ba48dc..a0d3769 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 <c.h>
 #include "stringutils.h"
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
-
 #include <stdio.h>
 
-#include <postgres.h>
-#ifndef HAVE_STRDUP
-#include <strdup.h>
-#endif
 #include <libpq-fe.h>
 
 
 
-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 914871d..4201fd5 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 92112ce..50a15fc 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 9658949..7a3bff4 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 92d3291..94bf6bf 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 406ab49..8bba82e 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 e31b66a..6a7fd71 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 ff6acef..d171c45 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 e54167c..3b9102d 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("<tr>", 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 8acb622..66437a9 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 <table ...> */
                char       *caption;    /* HTML <caption> */
@@ -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 bb6f193..16555d9 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 dc006e5..f70d913 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 b70170d..0142544 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 6988bcd..91f7df1 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)