<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
<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>
<function>PQpass</function>
Returns the password of the connection.
<synopsis>
-const char *PQpass(const PGconn *conn)
+char *PQpass(const PGconn *conn)
</synopsis>
</para>
</listitem>
<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>
<function>PQport</function>
Returns the port of the connection.
<synopsis>
-const char *PQport(const PGconn *conn)
+char *PQport(const PGconn *conn)
</synopsis>
</para>
</listitem>
<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>
<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>
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>
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>
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
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>
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
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>
<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
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.
const PQprintOpt *po);
struct {
- int header; /* print output field headings and row count */
- int align; /* fill align the fields */
- int standard; /* old brain dead format */
- int html3; /* output html tables */
- int expanded; /* expand tables */
- int pager; /* use pager for output if needed */
+ pqbool header; /* print output field headings and row count */
+ pqbool align; /* fill align the fields */
+ pqbool standard; /* old brain dead format */
+ pqbool html3; /* output html tables */
+ pqbool expanded; /* expand tables */
+ pqbool pager; /* use pager for output if needed */
char *fieldSep; /* field separator */
char *tableOpt; /* insert to HTML <table ...> */
char *caption; /* HTML <caption> */
char **fieldName; /* null terminated array of replacement field names */
} PQprintOpt;
</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>
<!--
-$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
-->
<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.
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>
</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>
(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>
<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
<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>
<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>
<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>
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
<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>
<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>
<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
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>
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 < <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>
<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>
</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>
<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.
<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>
<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>
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>
<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>
</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
<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>
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).
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:
</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>
*
* 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
/*----------
*
* '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.
*----------
{
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
my_line[blank_loc] = '\0';
}
- options[0] = NULL;
-
- if (options_string)
- {
- char quote;
- unsigned int pos;
-
- options_string = &options_string[strspn(options_string, " \t")]; /* skip leading
- * whitespace */
-
- i = 0;
- token = strtokx(options_string, " \t", "\"'`", '\\', "e, &pos, pset.encoding);
-
- for (i = 0; token && i < NR_OPTIONS; i++)
- {
- switch (quote)
- {
- case '"':
- options[i] = unescape(token);
- break;
- case '\'':
- options[i] = xstrdup(token);
- break;
- case '`':
- {
- bool error = false;
- FILE *fd = NULL;
- char *file = unescape(token);
- PQExpBufferData output;
- char buf[512];
- size_t result;
-
- fd = popen(file, "r");
- if (!fd)
- {
- psql_error("%s: %s\n", file, strerror(errno));
- error = true;
- }
-
- if (!error)
- {
- initPQExpBuffer(&output);
-
- do
- {
- result = fread(buf, 1, 512, fd);
- if (ferror(fd))
- {
- psql_error("%s: %s\n", file, strerror(errno));
- error = true;
- break;
- }
- appendBinaryPQExpBuffer(&output, buf, result);
- } while (!feof(fd));
- appendPQExpBufferChar(&output, '\0');
-
- if (pclose(fd) == -1)
- {
- psql_error("%s: %s\n", file, strerror(errno));
- error = true;
- }
- }
-
- if (!error)
- {
- if (output.data[strlen(output.data) - 1] == '\n')
- output.data[strlen(output.data) - 1] = '\0';
- }
-
- free(file);
- if (!error)
- options[i] = output.data;
- else
- {
- options[i] = xstrdup("");
- termPQExpBuffer(&output);
- }
- break;
- }
- case 0:
- default:
- if (token[0] == '\\')
- continue_parse = options_string + pos;
- else if (token[0] == '$')
- {
- const char * value = GetVariable(pset.vars, token+1);
- if (!value)
- value = "";
- options[i] = xstrdup(value);
- }
- else
- options[i] = xstrdup(token);
- }
-
- if (continue_parse)
- break;
-
- token = strtokx(NULL, " \t", "\"'`", '\\', "e, &pos, pset.encoding);
- } /* for */
-
- options[i] = NULL;
- }
-
- cmd = my_line;
- status = exec_command(cmd, options, options_string, query_buf);
+ status = exec_command(my_line, options_string, &continue_parse, query_buf);
if (status == CMD_UNKNOWN)
{
-
/*
- * If the command was not recognized, try inserting a space after
- * the first letter and call again. The one letter commands allow
- * arguments to start immediately after the command, but that is
- * no longer encouraged.
+ * If the command was not recognized, try inserting a space after the
+ * first letter and call again. The one letter commands allow arguments
+ * to start immediately after the command, but that is no longer
+ * encouraged.
*/
- const char *new_options[NR_OPTIONS+1];
char new_cmd[2];
- int i;
-
- for (i = 1; i < NR_OPTIONS+1; i++)
- new_options[i] = options[i - 1];
- new_options[0] = cmd + 1;
- new_cmd[0] = cmd[0];
+ new_cmd[0] = my_line[0];
new_cmd[1] = '\0';
- status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf);
+ status = exec_command(new_cmd, my_line + 1, &continue_parse, query_buf);
+
+ if (status != CMD_UNKNOWN && isalpha(new_cmd[0]))
+ psql_error("Warning: this syntax is deprecated\n");
}
if (status == CMD_UNKNOWN)
{
if (pset.cur_cmd_interactive)
- fprintf(stderr, "Invalid command \\%s. Try \\? for help.\n", cmd);
+ fprintf(stderr, "Invalid command \\%s. Try \\? for help.\n", my_line);
else
- psql_error("invalid command \\%s\n", cmd);
+ psql_error("invalid command \\%s\n", my_line);
status = CMD_ERROR;
}
- if (continue_parse && *(continue_parse + 1) == '\\')
+ if (continue_parse && *continue_parse && *(continue_parse + 1) == '\\')
continue_parse += 2;
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;
-
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)
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)
/* \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':
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);
}
* the query buffer
*/
else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
- status = do_edit(options[0], query_buf) ? CMD_NEWEDIT : CMD_ERROR;
+ {
+ char * fname;
+ if (!query_buf)
+ {
+ psql_error("no query buffer");
+ status = CMD_ERROR;
+ }
+ else
+ {
+ fname = scan_option(&string, OT_NORMAL, NULL);
+ status = do_edit(fname, query_buf) ? CMD_NEWEDIT : CMD_ERROR;
+ free(fname);
+ }
+ }
- /* \echo */
- else if (strcmp(cmd, "echo") == 0)
+ /* \echo and \qecho */
+ else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho")==0)
{
- int i;
+ char * value;
+ char quoted;
+ bool no_newline = false;
+ bool first = true;
+ FILE * fout;
+
+ if (strcmp(cmd, "qecho")==0)
+ fout = pset.queryFout;
+ else
+ fout = stdout;
- for (i = 0; i < 16 && options[i]; i++)
- fputs(options[i], stdout);
- fputs("\n", stdout);
+ while((value = scan_option(&string, OT_NORMAL, "ed)))
+ {
+ if (!quoted && strcmp(value, "-n")==0)
+ no_newline = true;
+ else
+ {
+ if (first)
+ first = false;
+ else
+ fputc(' ', fout);
+ fputs(value, fout);
+ }
+ free(value);
+ }
+ if (!no_newline)
+ fputs("\n", fout);
}
/* \f -- change field separator */
else if (strcmp(cmd, "f") == 0)
- success = do_pset("fieldsep", options[0], &pset.popt, quiet);
+ {
+ char * fname = scan_option(&string, OT_NORMAL, NULL);
+ success = do_pset("fieldsep", fname, &pset.popt, quiet);
+ free(fname);
+ }
/* \g means send query */
else if (strcmp(cmd, "g") == 0)
{
- if (!options[0])
+ char * fname = scan_option(&string, OT_NORMAL, NULL);
+ if (!fname)
pset.gfname = NULL;
else
- pset.gfname = xstrdup(options[0]);
+ pset.gfname = xstrdup(fname);
+ free(fname);
status = CMD_SEND;
}
/* help */
else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
{
- char buf[256] = "";
- int i;
- for (i=0; options && options[i] && strlen(buf)<255; i++)
- {
- strncat(buf, options[i], 255 - strlen(buf));
- if (strlen(buf)<255 && options[i+1])
- strcat(buf, " ");
- }
- buf[255] = '\0';
- helpSQL(buf);
+ helpSQL(options_string ? &options_string[strspn(options_string, " \t")] : NULL);
+ /* set pointer to end of line */
+ if (string)
+ string += strlen(string);
}
/* HTML mode */
/* \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)
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)
/* \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)
{
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;
}
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 */
/* \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)
{
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 */
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
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,
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)
{
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;
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;
-
/* do_connect
* -- handler for \connect
*
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;
/*
* 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)
static bool
editFile(const char *fname)
{
- char *editorName;
+ const char *editorName;
char *sys;
int result;
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);
#endif
-#ifdef USE_ASSERT_CHECKING
- assert(query_buf);
-#else
- if (!query_buf)
- return false;
-#endif
-
-
if (filename_arg)
fname = filename_arg;
if (!filename)
return false;
-#ifdef __CYGWIN32__
- fd = fopen(filename, "rb");
-#else
fd = fopen(filename, "r");
-#endif
if (!fd)
{
-#define DEFAULT_SHELL "/bin/sh"
+#define DEFAULT_SHELL "/bin/sh"
static bool
do_shell(const char *command)
if (!command)
{
char *sys;
- char *shellName;
+ const char *shellName;
shellName = getenv("SHELL");
if (shellName == NULL)
*
* 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"
#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)
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);
/*
* Error reporting for scripts. Errors should look like
- * filename:lineno: message
+ * psql:filename:lineno: message
*
*/
void
va_end(ap);
}
-/* for backend NOTICES */
+
+/*
+ * for backend NOTICES
+ */
void
NoticeProcessor(void * arg, const char * message)
{
#ifdef HAVE_TERMIOS_H
struct termios t_orig,
t;
-
#endif
destination = (char *) malloc(maxlen + 2);
* 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;
#
# 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 $
#################################################################
#
static struct _helpStruct QL_HELP[] = {
";
+$count = 0;
+
foreach $file (sort readdir DIR) {
my ($cmdname, $cmddesc, $cmdsynopsis);
$file =~ /\.sgml$/ || next;
$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";
{ NULL, NULL, NULL } /* End of list marker */
};
+
+#define QL_HELP_COUNT $count
+
+
#endif /* $define */
";
*
* 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"
if (name)
{
- strcat(buf, " AND a.aggname ~* '");
+ strcat(buf, " AND a.aggname ~* '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
if (name)
{
- strcat(buf, " AND a.aggname ~* '");
+ strcat(buf, " AND a.aggname ~* '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
if (name)
{
- strcat(buf, " AND p.proname ~* '");
+ strcat(buf, " AND p.proname ~* '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
if (name)
{
- strcat(buf, " AND t.typname ~* '");
+ strcat(buf, " AND t.typname ~* '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "' ");
}
" 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");
}
" 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");
}
" 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");
}
" relname !~ '^pg_'\n");
if (name)
{
- strcat(descbuf, " AND relname ~ '");
+ strcat(descbuf, " AND relname ~ '^");
strncat(descbuf, name, REGEXP_CUTOFF);
strcat(descbuf, "'\n");
}
"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");
}
"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");
}
"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");
}
"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");
}
"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");
}
"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");
}
"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");
}
tmp = malloc(size);
if (!tmp)
{
- psql_error("out of memory");
+ psql_error("out of memory\n");
exit(EXIT_FAILURE);
}
return tmp;
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] == '_')
/* Description */
if (desc)
- cells[i * cols + cols-1] = (char*)PQgetvalue(res, i, 7);
+ cells[i * cols + cols-1] = PQgetvalue(res, i, 7);
}
/* Make title */
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");
}
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");
}
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");
}
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");
}
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");
}
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");
}
"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");
}
" 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");
}
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
{
*
* 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"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
+#include <errno.h>
#ifndef WIN32
#include <sys/ioctl.h> /* for ioctl() */
#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>
#ifndef WIN32
struct passwd *pw = NULL;
-
#endif
/* Find default user, in case we need it. */
user = pw->pw_name;
else
{
- perror("getpwuid()");
+ psql_error("could not get current user name: %s", strerror(errno));
exit(EXIT_FAILURE);
}
#else
}
/* 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");
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=)");
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 */
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)");
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'");
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");
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");
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
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);
}
}
-
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."
+ );
}
*
* 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 :) */
* The result is malloced.
*/
char *
-gets_interactive(const char *prompt)
+gets_interactive(char *prompt)
{
char *s;
#ifdef USE_HISTORY
#ifdef USE_READLINE
if (useReadline)
- s = readline((char *) prompt);
+ s = readline(prompt);
else
{
#endif
if (flags == 1)
{
useReadline = true;
- rl_readline_name = "psql";
initialize_readline();
}
#endif
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;
*
* 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 */
*
* 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"
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 :( */
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);
*
* 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"
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,
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
}
/* start of quote */
- else if (line[i] == '\'' || line[i] == '"')
+ else if (!was_bslash && (line[i] == '\'' || line[i] == '"'))
in_quote = line[i];
/* in extended comment? */
*
* 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"
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)
{
*
* 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"
#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
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");
case PROMPT_COMMENT:
buf[0] = '*';
break;
+ case PROMPT_PAREN:
+ buf[0] = '(';
+ break;
default:
buf[0] = '\0';
break;
}
/* 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)
*
* 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
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 */
*
* 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
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;
char *password = NULL;
bool need_pass;
- memset(&pset, 0, sizeof pset);
-
if (!strrchr(argv[0], SEP_CHAR))
pset.progname = argv[0];
else
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
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
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)
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);
}
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 */
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'},
{"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'},
};
int optindex;
-#endif
+#endif /* HAVE_GETOPT_LONG */
extern char *optarg;
extern int optind;
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)
{
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;
case 'q':
SetVariable(pset.vars, "QUIET", "");
break;
+ case 'R':
+ pset.popt.topt.recordSep = xstrdup(optarg);
+ break;
case 's':
SetVariable(pset.vars, "SINGLESTEP", "");
break;
if (home)
{
- psqlrc = (char *) malloc(strlen(home) + 20);
+ psqlrc = malloc(strlen(home) + 20);
if (!psqlrc)
{
fprintf(stderr, "%s: out of memory\n", pset.progname);
#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.");
}
*
* 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);
/*
strtokx(const char *s,
const char *delim,
const char *quote,
- char escape,
+ int escape,
char *was_quoted,
unsigned int *token_pos,
int encoding)
char *start;
char *cp = NULL;
+#ifndef MULTIBYTE
+ (void)encoding; /*not used*/
+#endif
+
if (s)
{
free(storage);
* 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,
assert(source);
#endif
- destination = (char *) calloc(1, strlen(source) + 1);
+ destination = calloc(1, strlen(source) + 1);
if (!destination)
{
perror("calloc");
*
* 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
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);
*
* 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 $
*/
/*-----------
{ "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 */
};
* 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 $
*
*-------------------------------------------------------------------------
*/
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:
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
}
/* =========== accessor functions for PGconn ========= */
-const char *
+char *
PQdb(const PGconn *conn)
{
if (!conn)
return conn->dbName;
}
-const char *
+char *
PQuser(const PGconn *conn)
{
if (!conn)
return conn->pguser;
}
-const char *
+char *
PQpass(const PGconn *conn)
{
if (!conn)
return conn->pgpass;
}
-const char *
+char *
PQhost(const PGconn *conn)
{
if (!conn)
return conn->pghost;
}
-const char *
+char *
PQport(const PGconn *conn)
{
if (!conn)
return conn->pgport;
}
-const char *
+char *
PQtty(const PGconn *conn)
{
if (!conn)
return conn->pgtty;
}
-const char *
+char *
PQoptions(const PGconn *conn)
{
if (!conn)
return conn->status;
}
-const char *
+char *
PQerrorMessage(const PGconn *conn)
{
static char noConn[] = "PQerrorMessage: conn pointer is NULL\n";
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);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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",
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)
/*
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))
return 0;
}
-const char *
-PQcmdStatus(const PGresult *res)
+char *
+PQcmdStatus(PGresult *res)
{
if (!res)
return NULL;
if the last command was an INSERT, return the oid string
if not, return ""
*/
-const char *
+char *
PQoidStatus(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];
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)
{
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))
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
*
*/
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
int
PQmblen(const unsigned char *s, int encoding)
{
+ (void)s;
+ (void)encoding;
return 1;
}
int
* 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 $
*
*-------------------------------------------------------------------------
*/
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()
fputs("<tr>", fout);
else
{
- int j; /* for loop index */
int tot = 0;
int n = 0;
char *p = NULL;
-#if 0
/*
* really old printing routines
*/
}
}
}
-#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);
+}
* 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 $
*
*-------------------------------------------------------------------------
*/
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.
*/
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> */
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);
/* 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);
const PGresult *res,
const PQprintOpt *ps); /* option structure */
-#if 0
/*
* really old printing routines
*/
int terseOutput, /* delimiter bars */
int width); /* width of column, if
* 0, use variable width */
-#endif
+
/* === in fe-lobj.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);
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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 */
printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{
va_list args;
- int avail,
- nprinted;
+ size_t avail;
+ int nprinted;
resetPQExpBuffer(str);
appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{
va_list args;
- int avail,
- nprinted;
+ size_t avail;
+ int nprinted;
for (;;)
{
* 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))
* 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 $
*
*-------------------------------------------------------------------------
*/
typedef struct PQExpBufferData
{
char *data;
- int len;
- int maxlen;
+ size_t len;
+ size_t maxlen;
} PQExpBufferData;
typedef PQExpBufferData *PQExpBuffer;
*
* 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
* if necessary.
*/
extern void appendBinaryPQExpBuffer(PQExpBuffer str,
- const char *data, int datalen);
+ const char *data, size_t datalen);
#endif /* PQEXPBUFFER_H */
* 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)