mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Fixed psql variables vs array syntax, as well as minor psql enhancements
This commit is contained in:
parent
4ceb2d0cb6
commit
7c9390caa1
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.19 2000/01/12 19:36:34 petere Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.20 2000/01/14 22:18:01 petere Exp $
|
||||
Postgres documentation
|
||||
-->
|
||||
|
||||
@ -32,27 +32,20 @@ Postgres documentation
|
||||
<date>1998-09-26</date>
|
||||
</refsect2info>
|
||||
|
||||
<title>Input</title>
|
||||
<title>Summary</title>
|
||||
|
||||
<para>
|
||||
<application>psql</application> accepts many command-line arguments,
|
||||
a rich set of meta-commands, and the full <acronym>SQL</acronym> language
|
||||
supported by <productname>PostgreSQL</productname>.
|
||||
<application>psql</application> is a terminal-based front-end to
|
||||
<productname>PostgreSQL</productname>. It enables you to type in queries
|
||||
interactively, issue them to <productname>PostgreSQL</productname>, and see
|
||||
the query results. Alternatively, input can be from a file.
|
||||
In addition, it provides a number of meta-commands and
|
||||
various shell-like features to facilitate writing scripts and automating a wide
|
||||
variety of tasks.
|
||||
</para>
|
||||
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="R2-APP-PSQL-2">
|
||||
<refsect2info>
|
||||
<date>1998-10-26</date>
|
||||
</refsect2info>
|
||||
|
||||
<title>Output</title>
|
||||
<para>
|
||||
<application>psql</application> returns 0 to the shell on successful
|
||||
completion of all queries, 1 for fatal errors, 2 for abrupt disconnection
|
||||
from the backend, and 3 if a non-interactive script stopped because an <acronym>SQL</acronym>
|
||||
command or psql meta-command resulted in an error.
|
||||
</para>
|
||||
</refsect2>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1 id="R1-APP-PSQL-1">
|
||||
@ -62,58 +55,31 @@ Postgres documentation
|
||||
|
||||
<title>Description</title>
|
||||
|
||||
<para>
|
||||
<application>psql</application> is a character-based front-end to
|
||||
<productname>PostgreSQL</productname>. It enables you to type in queries
|
||||
interactively, issue them to <productname>PostgreSQL</productname>, and see
|
||||
the query results. In addition, it provides a number of meta-commands and
|
||||
various shell-like features to facilitate writing scripts and automating a wide
|
||||
variety of tasks.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<application>psql</application> is a regular
|
||||
<productname>PostgreSQL</productname> client application. Hence, a
|
||||
<application>postmaster</application> process must be running on the database
|
||||
server host before <application>psql</application> is executed. In addition,
|
||||
the correct parameters to identify the database server, such as the
|
||||
<application>postmaster</application> host name, may need to be specified as
|
||||
described below.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When <application>psql</application> starts, it reads <acronym>SQL</acronym> and psql commands
|
||||
from <filename>/etc/psqlrc</filename> and then from
|
||||
<filename>$<envar>HOME</envar>/.psqlrc</filename>
|
||||
This allows commands like <command>\set</command> or the <acronym>SQL</acronym> command
|
||||
<xref linkend="SQL-SET" endterm="SQL-SET-title">, which can be used to set a variety of options,
|
||||
to be run at the start of every session.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<application>psql</application> can be used in a pipe sequence, and
|
||||
automatically detects when it is not used interactively.
|
||||
</para>
|
||||
|
||||
<refsect2 id="R2-APP-PSQL-3">
|
||||
<refsect2 id="R2-APP-PSQL-connecting">
|
||||
<refsect2info>
|
||||
<date>1998-09-26</date>
|
||||
<date>2000-01-14</date>
|
||||
</refsect2info>
|
||||
|
||||
<title>Connecting To A Database</title>
|
||||
|
||||
<para>
|
||||
<application>psql</application> attempts to make a connection to the
|
||||
database name at the hostname and port number, and with the user name
|
||||
specified on the command line. If any of these are omitted, the
|
||||
<application>libpq</application> client library, upon which
|
||||
<application>psql</application> is built, will choose defaults.
|
||||
(This will usually mean the environment variables <envar>PGDATABASE</envar>,
|
||||
<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
|
||||
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.
|
||||
If an argument is found that does not belong to any option it will be interpreted
|
||||
as database name as well. Not all these options are required, defaults do apply.
|
||||
If you omit the host name psql will connect via domain sockets to a server on the
|
||||
local host. The default port number is compile-time determined. Since the database
|
||||
server uses the same default, chances are you don't have to specify the port in most
|
||||
settings. The default user name is your Unix username, the same with the database.
|
||||
Note that you can't just connect to any database under any username. Your database
|
||||
administrator should have informed you about your access rights. To save you some typing
|
||||
you can also set the environment variables <envar>PGDATABASE</envar>,
|
||||
<envar>PGHOST</envar>, <envar>PGPORT</envar>, <envar>PGUSER</envar>,
|
||||
respectively, if they are set. Otherwise the default host is the local host
|
||||
via Unix domain sockets, the default port is decided at compile time,
|
||||
the default user is the system user name, and the default database is
|
||||
the one with the same name as the user.)
|
||||
respectively to appropriate values.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -151,8 +117,9 @@ testdb=>
|
||||
<para>
|
||||
At the prompt, the user may type in <acronym>SQL</acronym> queries.
|
||||
Ordinarily, input lines are sent to the backend when a query-terminating
|
||||
semicolon is reached. If the database server reports success, the query
|
||||
results are displayed on the screen.
|
||||
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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -173,12 +140,11 @@ testdb=>
|
||||
|
||||
<para>
|
||||
Anything you enter in <application>psql</application> that begins with an
|
||||
unquoted backslash is a <application>psql</application> meta-command.
|
||||
Anything else is <acronym>SQL</acronym> and simply goes into the current
|
||||
query buffer (and once you have at least one complete query, it gets
|
||||
automatically submitted to the backend). For this reason,
|
||||
<application>psql</application> meta-commands are more commonly called
|
||||
slash or backslash commands.
|
||||
unquoted backslash is a <application>psql</application> meta-command that is
|
||||
processes by <application>psql</application> itself.
|
||||
These commands are what makes
|
||||
<application>psql</application> interesting for administration or scripting.
|
||||
Meta-commands are more commonly called slash or backslash commands.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -268,11 +234,8 @@ testdb=>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If <replaceable class="parameter">username</replaceable> is omitted or
|
||||
<literal>-</literal> the current user name is assumed. If
|
||||
<replaceable class="parameter">username</replaceable> is <literal>?</literal>
|
||||
<application>psql</application> will prompt for the new user name
|
||||
interactively.
|
||||
If <replaceable class="parameter">username</replaceable> is omitted
|
||||
the current user name is assumed.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -293,10 +256,11 @@ testdb=>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>\copy</literal> [ <literal>binary</literal> ] <replaceable class="parameter">table</replaceable>
|
||||
<term><literal>\copy</literal> <replaceable class="parameter">table</replaceable>
|
||||
[ <literal>with oids</literal> ] { <literal>from</literal> | <literal>to</literal> }
|
||||
<replaceable class="parameter">filename</replaceable> [ <literal>with delimiters</literal>
|
||||
'<replaceable class="parameter">character</replaceable>' ]
|
||||
<replaceable class="parameter">filename</replaceable> | stdin | stdout
|
||||
[ <literal>with delimiters</literal> '<replaceable class="parameter">characters</replaceable>' ]
|
||||
[ <literal>with null as</literal> '<replaceable class="parameter">string</replaceable>' ]
|
||||
</term>
|
||||
|
||||
<listitem>
|
||||
@ -326,6 +290,18 @@ testdb=>
|
||||
technique may be preferable.
|
||||
</para>
|
||||
</tip>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Note the difference in interpretation of <literal>stdin</literal> and <literal>stdout</literal>
|
||||
between frontend and backend copies: In a frontend copy these always refer
|
||||
to <application>psql</application>'s input and output stream. On a backend
|
||||
copy <literal>stdin</literal> comes from whereever the <command>COPY</command>
|
||||
itself came from (for example, a script ran with the <option>-f</option>) option,
|
||||
and <literal>stdout</literal> refers to the query output stream (see
|
||||
<command>\o</command> meta-command below).
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -666,7 +642,7 @@ Tue Oct 26 21:40:57 CEST 1999
|
||||
</tip>
|
||||
<note>
|
||||
<para>
|
||||
See the description of the <envar>lo_transaction</envar> variable for
|
||||
See the description of the <envar>LO_TRANSACTION</envar> variable for
|
||||
important information concerning all large object operations.
|
||||
</para>
|
||||
</note>
|
||||
@ -689,7 +665,7 @@ lo_import 152801
|
||||
which one ought to remember if one wants to access the object ever again.
|
||||
For that reason it is recommended to always associate a human-readable
|
||||
comment with every object. Those can then be seen with the
|
||||
<command>\lo_list?</command> command.
|
||||
<command>\lo_list</command> command.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -700,7 +676,7 @@ lo_import 152801
|
||||
|
||||
<note>
|
||||
<para>
|
||||
See the description of the <envar>lo_transaction</envar> variable for
|
||||
See the description of the <envar>LO_TRANSACTION</envar> variable for
|
||||
important information concerning all large object operations.
|
||||
</para>
|
||||
</note>
|
||||
@ -733,7 +709,7 @@ lo_import 152801
|
||||
</tip>
|
||||
<note>
|
||||
<para>
|
||||
See the description of the <envar>lo_transaction</envar> variable for
|
||||
See the description of the <envar>LO_TRANSACTION</envar> variable for
|
||||
important information concerning all large object operations.
|
||||
</para>
|
||||
</note>
|
||||
@ -755,9 +731,11 @@ lo_import 152801
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<quote>Query results</quote> includes all tables and notices obtained
|
||||
<quote>Query results</quote> includes all tables, command responses,
|
||||
and notices obtained
|
||||
from the database server, as well as output of various backslash
|
||||
commands that query the database (such as <command>\d</command>).
|
||||
commands that query the database (such as <command>\d</command>),
|
||||
but not error messages.
|
||||
</para>
|
||||
|
||||
<tip>
|
||||
@ -922,7 +900,7 @@ lo_import 152801
|
||||
<para>
|
||||
Toggles the list of a pager to do table output. If the environment variable
|
||||
<envar>PAGER</envar> is set, the output is piped to the specified program.
|
||||
Otherwise <filename>/bin/more</filename> is assumed.
|
||||
Otherwise <filename>more</filename> is used.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -1024,10 +1002,8 @@ lo_import 152801
|
||||
<para>
|
||||
Sets the internal variable <replaceable class="parameter">name</replaceable>
|
||||
to <replaceable class="parameter">value</replaceable>. If no second argument
|
||||
is given, the variable is unset (which is different from setting it to,
|
||||
for example, an empty string: <literal>\set foo ''</literal>). If no
|
||||
arguments are given, all currently defined variables are listed with their
|
||||
values.
|
||||
is given, the variable is just set with not value. To unset a variable, use
|
||||
the <command>\unset</command> command.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -1192,14 +1168,7 @@ Access permissions for database "test"
|
||||
<para>
|
||||
If so configured, <application>psql</application> understands both standard
|
||||
Unix short options, and <acronym>GNU</acronym>-style long options. The latter
|
||||
are not available on all systems, so you are advised to consider carefully
|
||||
whether to use them.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Many command line options are equivalent to an internal slash command or to
|
||||
setting some variable. Those will not be explained in detail here. Instead,
|
||||
you are asked to look them up in the respective section.
|
||||
are not available on all systems.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -1221,8 +1190,7 @@ Access permissions for database "test"
|
||||
<para>
|
||||
Specifies that <application>psql</application>
|
||||
is to execute one query string, <replaceable class="parameter">query</replaceable>,
|
||||
and then exit. This is useful for shell scripts, typically in
|
||||
conjunction with the <option>-q</option> option.
|
||||
and then exit. This is useful for shell scripts.
|
||||
</para>
|
||||
<para>
|
||||
<replaceable class="parameter">query</replaceable> must be either a query string
|
||||
@ -1254,20 +1222,20 @@ Access permissions for database "test"
|
||||
<listitem>
|
||||
<para>
|
||||
In non-interactive mode, all lines are printed to the screen as they are read.
|
||||
This is equivalent to setting the variable <envar>echo</envar>.
|
||||
This is equivalent to setting the variable <envar>ECHO</envar> to <literal>full</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>-E, --echo-all</term>
|
||||
<term>-E, --echo-hidden</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Echos the actual queries generated by \d and other backslash commands.
|
||||
You can use this if you wish to include similar functionality into
|
||||
your own programs. This is equivalent to setting the variable
|
||||
<envar>echo_secret</envar> from within <application>psql</application>.
|
||||
<envar>ECHO_HIDDEN</envar> from within <application>psql</application>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -1337,7 +1305,7 @@ Access permissions for database "test"
|
||||
<term>-n, --no-readline</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Do not use the readline library for input line editing and command history.
|
||||
Do not use readline for line editing and do not use the history.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -1389,7 +1357,7 @@ Access permissions for database "test"
|
||||
By default, it prints welcome messages and various informational output.
|
||||
If this option is used, none of this happens. This is useful with the
|
||||
<option>-c</option> option. Within <application>psql</application> you can
|
||||
also set the <envar>quiet</envar> variable to achieve the same effect.
|
||||
also set the <envar>QUIET</envar> variable to achieve the same effect.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -1411,7 +1379,7 @@ Access permissions for database "test"
|
||||
<term>-S, --single-line</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Runs in single-line mode where a newline sends a query, in addition to a semicolon.
|
||||
Runs in single-line mode where a newline terminates a query, like a semicolon would do.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
@ -1419,8 +1387,7 @@ Access permissions for database "test"
|
||||
This mode is provided for those who insist on it, but you are not necessarily
|
||||
encouraged to use it. In particular, if you mix <acronym>SQL</acronym> and
|
||||
meta-commands on a line the order of execution might not always be clear to
|
||||
the unexperienced user. Moral: Unless you exclusively type short queries,
|
||||
avoid using this mode.
|
||||
the unexperienced user.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
@ -1472,9 +1439,7 @@ Access permissions for database "test"
|
||||
<listitem>
|
||||
<para>
|
||||
Connects to the database as the user <replaceable class="parameter">username</replaceable>
|
||||
instead of the default. (You must have permission to do so, of course.) If
|
||||
<replaceable class="parameter">username</replaceable> is <quote>?</quote>, <application>psql</application>
|
||||
issues an interactive prompt for the user name.
|
||||
instead of the default. (You must have permission to do so, of course.)
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -1486,7 +1451,9 @@ Access permissions for database "test"
|
||||
<para>
|
||||
Performs a variable assignment, like the <command>\set</command> internal command.
|
||||
Note that you must separate name and value, if any, by an equal sign on the command
|
||||
line.
|
||||
line. To unset a variable, leave off the equal sign. These assignments are done
|
||||
during a very early state of startup, so variables reserved for internal purposes
|
||||
might get overwritten again.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -1503,7 +1470,7 @@ Access permissions for database "test"
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>-W</term>
|
||||
<term>-W, --password</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Requests that <application>psql</application> should prompt for a password
|
||||
@ -1518,22 +1485,14 @@ Access permissions for database "test"
|
||||
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 content of the environment variable <envar>PGPASSWORD</envar> is
|
||||
taken. If this is not set, the connection attempt will fail.
|
||||
the connection attempt will fail.
|
||||
</para>
|
||||
|
||||
<caution>
|
||||
<para>
|
||||
If you are considering setting the variable <envar>PGPASSWORD</envar> to do
|
||||
authentication, you have a problem.
|
||||
</para>
|
||||
</caution>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>-x</term>
|
||||
<term>-x, --expanded</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Turns on extended row format mode. This is equivalent to the command
|
||||
@ -1542,15 +1501,19 @@ Access permissions for database "test"
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>-?, --help</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Shows help about <application>psql</application> command line arguments.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You may set environment variables to avoid typing some of the above
|
||||
options. See the section <quote>Connection To A Database</quote> above
|
||||
and in particular the documentation of the <application>libpq</application>
|
||||
client library.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
||||
@ -1585,7 +1548,7 @@ bar
|
||||
testdb=> <userinput>\echo "foo is now ${foo}."</userinput>
|
||||
foo is now bar.
|
||||
</programlisting>
|
||||
(The curly braces are required. This is not <productname>Perl</productname>.) No variable substitution
|
||||
(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>
|
||||
@ -1604,76 +1567,52 @@ foo is now bar.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
If you call <command>\set</command> without an argument, the variable is simply
|
||||
set, but has no value. To unset (or delete) a variable, use the command
|
||||
<command>\unset</command>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<application>psql</application>'s internal variable names can consist of
|
||||
letters, numbers, and underscores in any order and any number of them.
|
||||
It is recommended, however, that you stick to lower-case letters and do not
|
||||
begin with a digit. The partial rationale for this follows.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you attempt to refer to a variable that is not set,
|
||||
<application>psql</application> first checks if it is the name of one of
|
||||
several defined <quote>magic</quote> variables. Those variables are
|
||||
maintained internally and always have a value (at least when their semantics
|
||||
permit it). By convention they all start with an upper-case letter. You can
|
||||
set those variables manually, but that will <quote>shadow</quote> their
|
||||
special meaning, until you unset your personal copy. Finally, if no match is
|
||||
found that way, the value of the respective environment variable is
|
||||
substituted.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Currently, the following <quote>magic</quote> variables are defined:
|
||||
<envar>Version</envar> which contains a string with the version of
|
||||
<application>psql</application>; <envar>Database</envar>, <envar>Host</envar>,
|
||||
<envar>Port</envar>, <envar>User</envar> are the currently active
|
||||
connection options. <envar>LastOid</envar> contains the oid that was the
|
||||
result of the last <command>INSERT</command> or <command>\lo_import</command>
|
||||
command. If the last command was not one of those two, the value
|
||||
is undefined.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A number of regular variables are treated specially by <application>psql</application>.
|
||||
They indicate certain option settings that can be changed at runtime
|
||||
by altering the value of the variable. Although you can use these
|
||||
by altering the value of the variable or represent some state of the application.
|
||||
Although you can use these
|
||||
variables for any other purpose, this is not recommended, as the
|
||||
program behavior might grow really strange really quickly. Note that the
|
||||
majority variables are <quote>boolean</quote> variables, that is, they
|
||||
only care whether or not are they set, not what to. A list of all specially
|
||||
treated variables follows.
|
||||
program behavior might grow really strange really quickly.
|
||||
By convention, all specially treated variables consist of all upper-case letters
|
||||
(and possibly numbers and underscores). To ensure maximum compatibility in the
|
||||
future, avoid such variables.
|
||||
A list of all specially treated variables follows.
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><envar>die_on_error</envar></term>
|
||||
<term><envar>DBNAME</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
By default, if non-interactive scripts encounter an error, such as a
|
||||
malformed <acronym>SQL</acronym> query or internal meta-command,
|
||||
processing continues. This is often less than desirable. If this variable
|
||||
is set, script processing will immediately terminate. If the script was
|
||||
called from another script it will terminate in the same fashion.
|
||||
If the outermost script was not called from an interactive <application>psql</application>
|
||||
session but rather using the <option>-f</option> option, <application>psql</application>
|
||||
will return error code 3, to distinguish this case from fatal
|
||||
error conditions (error code 1).
|
||||
The name of the database you are currently connected to. This is set everytime
|
||||
you connect to a database (including program startup), but can be unset.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>echo</envar></term>
|
||||
<term><envar>ECHO</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If set, all lines from a script are written to the standard output before they
|
||||
are executed. To specify this on program startup, in conjunction with the
|
||||
If set to <quote><literal>full</literal></quote>, all lines entered or from a script
|
||||
are written to the standard output before they
|
||||
are parsed or executed. To specify this on program startup, in conjunction with the
|
||||
<option>-f</option> option perhaps, use the switch <option>-e</option>.
|
||||
If set to <quote><literal>brief</literal></quote>, <application>psql</application>
|
||||
merely prints all queries as they are sent to the backend.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>echo_secret</envar></term>
|
||||
<term><envar>ECHO_HIDDEN</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
When this variable is set and a backslash command queries the database, the query
|
||||
@ -1686,7 +1625,98 @@ foo is now bar.
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>lo_transaction</envar></term>
|
||||
<term><envar>EXIT_ON_ERROR</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
By default, if non-interactive scripts encounter an error, such as a
|
||||
malformed <acronym>SQL</acronym> query or internal meta-command,
|
||||
processing continues. This is has been the traditional behaviour of
|
||||
<application>psql</application>but is often less than desirable. If this variable
|
||||
is set, script processing will immediately terminate. If the script was
|
||||
called from another script it will terminate in the same fashion.
|
||||
If the outermost script was not called from an interactive <application>psql</application>
|
||||
session but rather using the <option>-f</option> option, <application>psql</application>
|
||||
will return error code 3, to distinguish this case from fatal
|
||||
error conditions (error code 1).
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>HISTCONTROL</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If this variable is set to <literal>ignorespace</literal>, lines which begin with a
|
||||
space are not entered into the history list. If set to a value of
|
||||
<literal>ignoredups</literal>, lines matching the previous history line are not
|
||||
entered. A value of <literal>ignoreboth</literal> combines the two
|
||||
options. If unset, or if set to any other value than those above, all lines read
|
||||
in interactive mode are saved on the history list.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
This feature was shamelessly plagiarized from <application>bash</application>.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>HISTSIZE</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The number of commands to store in the command history.
|
||||
The default value is 500.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
This feature was shamelessly plagiarized from <application>bash</application>.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>HOST</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The database server host you are currently connected to. This is set everytime
|
||||
you connect to a database (including program startup), but can be unset.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>IGNOREEOF</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If unset, sending an EOF character (usually Control-D) to an interactive session of
|
||||
<application>psql</application> will terminate the application.
|
||||
If set to a numeric value, that many EOF characters are ignored before the application
|
||||
terminates. If the variable is set but has no numeric value, the default is 10.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
This feature was shamelessly plagiarized from <application>bash</application>.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>LASTOID</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The value of the last affected oid, as returned from an <command>INSERT</command>
|
||||
or <command>lo_insert</command> commmand. This variable is only guaranteed to be
|
||||
valid until after the result of the next <acronym>SQL</acronym> command has been
|
||||
displayed.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>LO_TRANSACTION</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If you use the <productname>PostgreSQL</productname> large object
|
||||
@ -1702,7 +1732,7 @@ foo is now bar.
|
||||
all. In the latter case you must provide you own
|
||||
<command>BEGIN TRANSACTION</command>/<command>COMMIT</command> block or
|
||||
the results will be unpredictable (usually resulting in the desired
|
||||
action not being performed anyway).
|
||||
action not being performed in any case).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -1717,7 +1747,17 @@ foo is now bar.
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>prompt1</envar>, <envar>prompt2</envar>, <envar>prompt3</envar></term>
|
||||
<term><envar>PORT</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The database server port you are currently connected to. This is set everytime
|
||||
you connect to a database (including program startup), but can be unset.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>PROMPT1</envar>, <envar>PROMPT2</envar>, <envar>PROMPT3</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
These specify what the prompt <application>psql</application> issues is
|
||||
@ -1729,7 +1769,7 @@ foo is now bar.
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>quiet</envar></term>
|
||||
<term><envar>QUIET</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
This variable is equivalent to the command line option <option>-q</option>.
|
||||
@ -1739,7 +1779,7 @@ foo is now bar.
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>singleline</envar></term>
|
||||
<term><envar>SINGLELINE</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
This variable is set be the command line options <option>-S</option>. You
|
||||
@ -1749,13 +1789,24 @@ foo is now bar.
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>singlestep</envar></term>
|
||||
<term><envar>SINGLESTEP</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
This variable is equivalent to the command line option <option>-s</option>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>USER</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The database user you are currently connected as. This is set everytime
|
||||
you connect to a database (including program startup), but can be unset.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
@ -1814,6 +1865,15 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
|
||||
be better off preparing the file externally.
|
||||
</para>
|
||||
|
||||
<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
|
||||
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.)
|
||||
</para>
|
||||
|
||||
</refsect2>
|
||||
|
||||
|
||||
@ -1822,8 +1882,8 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
|
||||
|
||||
<para>
|
||||
The prompts <application>psql</application> issues can be customized to
|
||||
your preference. The three variables <envar>prompt1</envar>, <envar>prompt2</envar>,
|
||||
and <envar>prompt3</envar> contain strings and special escape sequences
|
||||
your preference. The three variables <envar>PROMPT1</envar>, <envar>PROMPT2</envar>,
|
||||
and <envar>PROMPT3</envar> contain strings and special escape sequences
|
||||
that describe the appearance of the prompt. Prompt 1 is the normal prompt
|
||||
that is issued when <application>psql</application> requests a new query.
|
||||
Prompt 2 is issued when more input is expected during query input because
|
||||
@ -1924,8 +1984,75 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
|
||||
and 2, and <literal>'>> '</literal> for prompt 3.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
This feature was shamelessly plagiarized from <application>tcsh</application>.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="APP-PSQL-MISC">
|
||||
<title id="APP-PSQL-MISC-title">Miscellaneous</title>
|
||||
|
||||
<para>
|
||||
<application>psql</application> returns 0 to the shell if it finished normally,
|
||||
1 if a fatal error of its own (out of memory, file not found) occurs, 2 if the
|
||||
connection to the backend went bad and the session is not interactive, and 3 if
|
||||
an error occurred in a script and the variable <envar>EXIT_ON_ERROR</envar> was
|
||||
set.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Before starting up in interactive mode, <application>psql</application> attempts
|
||||
to read and execute the files <filename>/etc/psqlrc</filename> and
|
||||
<filename>$HOME/.psqlrc</filename>. They could be used to set up the client or
|
||||
the server to taste (using the <command>\set</command> and <command>SET</command>
|
||||
commands).
|
||||
</para>
|
||||
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title><acronym>GNU</acronym> readline</title>
|
||||
|
||||
<para>
|
||||
<application>psql</application> supports the readline and history libraries for
|
||||
convenienent line editing and retrieval. The command history is stored in a file
|
||||
named <filename>.psqlrc</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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you have the readline library installed but <application>psql</application>
|
||||
does not seem to use it, you must make sure that <productname>PostgreSQL</productname>'s
|
||||
top-level <filename>configure</filename> script finds it. <filename>configure</filename>
|
||||
needs to find both the library <filename>libreadline.a</filename>
|
||||
(or <filename>libreadline.so</filename> on systems with shared libraries)
|
||||
<emphasis>and</emphasis> the header files <filename>readline.h</filename> and
|
||||
<filename>history.h</filename> (or <filename>readline/readline.h</filename> and
|
||||
<filename>readline/history.h</filename>) in appropriate directories. If
|
||||
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 ...
|
||||
</programlisting>
|
||||
Then you have to recompile <application>psql</application> (not necessarily
|
||||
the entire code tree).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <acronym>GNU</acronym> readline library can be obtained from the <acronym>GNU</acronym>
|
||||
project's <acronym>FTP</acronym> server at <ulink URL="ftp://ftp.gnu.org">ftp://ftp.gnu.org</ulink>.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
|
||||
|
||||
</refsect1>
|
||||
|
||||
|
||||
@ -2074,23 +2201,9 @@ Field separator is "oo".
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
There are about three different parsers in <application>psql</application>,
|
||||
in addition to the backend <acronym>SQL</acronym> parser, all doing their own thing
|
||||
and attempting to get along with each other. Sometimes they do, sometimes
|
||||
they don't. An excellent example of this can be seen in section
|
||||
<quote><xref linkend="APP-PSQL-sql-interpol" endterm="APP-PSQL-sql-interpol-title"></quote>.
|
||||
There are vague dreams of using <application>flex</application> in the future,
|
||||
but it won't happen soon.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Several string buffers are assigned fixed sizes at compile time. These
|
||||
are usually based on certain settings about what the backend can accept
|
||||
for a particular quantity. If you use <application>psql</application> with
|
||||
a different backend than the one it was configured for, you might encounter
|
||||
these limits sooner rather than later.
|
||||
<application>psql</application> only works smootly with servers of the
|
||||
same version. That does not mean other combinations will fail outright,
|
||||
but subtle and not-so-subtle problems might come up.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
@ -2098,7 +2211,7 @@ Field separator is "oo".
|
||||
<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 (see previous item). Not that there is any command
|
||||
to fixing this one day. Not that there is any command
|
||||
that actually uses that many options though.
|
||||
</para>
|
||||
</listitem>
|
||||
@ -2106,41 +2219,6 @@ Field separator is "oo".
|
||||
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title><acronym>GNU</acronym> readline</title>
|
||||
|
||||
<para>
|
||||
A great deal of <application>psql</application>'s convenience is owed to it
|
||||
using the <acronym>GNU</acronym> readline and history library for accepting
|
||||
and storing user input. To verify whether your copy of <application>psql</application>
|
||||
was compiled with readline support, execute <literal>psql -V</literal> and check the
|
||||
output for the words <quote>readline</quote> and <quote>history</quote>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you have the readline library installed but <application>psql</application>
|
||||
does not seem to use it, you must make sure that <productname>PostgreSQL</productname>'s
|
||||
top-level <filename>configure</filename> script finds it. <filename>configure</filename>
|
||||
needs to find both the library <filename>libreadline.a</filename>
|
||||
(or <filename>libreadline.so</filename> on systems with shared libraries)
|
||||
<emphasis>and</emphasis> the header files <filename>readline.h</filename> and
|
||||
<filename>history.h</filename> (or <filename>readline/readline.h</filename> and
|
||||
<filename>readline/history.h</filename>) in appropriate directories. If
|
||||
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 ...
|
||||
</programlisting>
|
||||
Then you have to recompile <application>psql</application> (not necessarily
|
||||
the entire code tree).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <acronym>GNU</acronym> readline library can be obtained from the <acronym>GNU</acronym>
|
||||
project's <acronym>FTP</acronym> server at <ulink URL="ftp://ftp.gnu.org">ftp://ftp.gnu.org</ulink>.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <config.h>
|
||||
#include <c.h>
|
||||
#include "command.h"
|
||||
|
||||
@ -26,6 +25,7 @@
|
||||
#include "print.h"
|
||||
#include "describe.h"
|
||||
#include "input.h"
|
||||
#include "variables.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define popen(x,y) _popen(x,y)
|
||||
@ -38,16 +38,14 @@
|
||||
static backslashResult exec_command(const char *cmd,
|
||||
char *const * options,
|
||||
const char *options_string,
|
||||
PQExpBuffer query_buf,
|
||||
PsqlSettings *pset);
|
||||
PQExpBuffer query_buf);
|
||||
|
||||
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
|
||||
|
||||
static char * unescape(const char *source, PsqlSettings *pset);
|
||||
static char * unescape(const char *source);
|
||||
|
||||
static bool do_connect(const char *new_dbname,
|
||||
const char *new_user,
|
||||
PsqlSettings *pset);
|
||||
const char *new_user);
|
||||
|
||||
|
||||
static bool do_shell(const char *command);
|
||||
@ -79,8 +77,7 @@ static bool do_shell(const char *command);
|
||||
*/
|
||||
|
||||
backslashResult
|
||||
HandleSlashCmds(PsqlSettings *pset,
|
||||
const char *line,
|
||||
HandleSlashCmds(const char *line,
|
||||
PQExpBuffer query_buf,
|
||||
const char **end_of_cmd)
|
||||
{
|
||||
@ -95,6 +92,12 @@ HandleSlashCmds(PsqlSettings *pset,
|
||||
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 = xstrdup(line);
|
||||
|
||||
/*
|
||||
@ -135,7 +138,7 @@ HandleSlashCmds(PsqlSettings *pset,
|
||||
switch (quote)
|
||||
{
|
||||
case '"':
|
||||
options[i] = unescape(token, pset);
|
||||
options[i] = unescape(token);
|
||||
break;
|
||||
case '\'':
|
||||
options[i] = xstrdup(token);
|
||||
@ -144,7 +147,7 @@ HandleSlashCmds(PsqlSettings *pset,
|
||||
{
|
||||
bool error = false;
|
||||
FILE *fd = NULL;
|
||||
char *file = unescape(token, pset);
|
||||
char *file = unescape(token);
|
||||
PQExpBufferData output;
|
||||
char buf[512];
|
||||
size_t result;
|
||||
@ -201,7 +204,12 @@ HandleSlashCmds(PsqlSettings *pset,
|
||||
if (token[0] == '\\')
|
||||
continue_parse = options_string + pos;
|
||||
else if (token[0] == '$')
|
||||
options[i] = xstrdup(interpolate_var(token + 1, pset));
|
||||
{
|
||||
const char * value = GetVariable(pset.vars, token+1);
|
||||
if (!value)
|
||||
value = "";
|
||||
options[i] = xstrdup(value);
|
||||
}
|
||||
else
|
||||
options[i] = xstrdup(token);
|
||||
}
|
||||
@ -216,7 +224,7 @@ HandleSlashCmds(PsqlSettings *pset,
|
||||
}
|
||||
|
||||
cmd = my_line;
|
||||
status = exec_command(cmd, options, options_string, query_buf, pset);
|
||||
status = exec_command(cmd, options, options_string, query_buf);
|
||||
|
||||
if (status == CMD_UNKNOWN)
|
||||
{
|
||||
@ -238,15 +246,15 @@ HandleSlashCmds(PsqlSettings *pset,
|
||||
new_cmd[0] = cmd[0];
|
||||
new_cmd[1] = '\0';
|
||||
|
||||
status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf, pset);
|
||||
status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf);
|
||||
}
|
||||
|
||||
if (status == CMD_UNKNOWN)
|
||||
{
|
||||
if (pset->cur_cmd_interactive)
|
||||
if (pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "Invalid command \\%s. Try \\? for help.\n", cmd);
|
||||
else
|
||||
fprintf(stderr, "%s: invalid command \\%s", pset->progname, cmd);
|
||||
fprintf(stderr, "%s: invalid command \\%s", pset.progname, cmd);
|
||||
status = CMD_ERROR;
|
||||
}
|
||||
|
||||
@ -254,13 +262,10 @@ HandleSlashCmds(PsqlSettings *pset,
|
||||
continue_parse += 2;
|
||||
|
||||
|
||||
if (end_of_cmd)
|
||||
{
|
||||
if (continue_parse)
|
||||
*end_of_cmd = line + (continue_parse - my_line);
|
||||
else
|
||||
*end_of_cmd = NULL;
|
||||
}
|
||||
*end_of_cmd = line + strlen(line);
|
||||
|
||||
/* clean up */
|
||||
for (i = 0; i < NR_OPTIONS && options[i]; i++)
|
||||
@ -278,12 +283,11 @@ static backslashResult
|
||||
exec_command(const char *cmd,
|
||||
char *const * options,
|
||||
const char *options_string,
|
||||
PQExpBuffer query_buf,
|
||||
PsqlSettings *pset)
|
||||
PQExpBuffer query_buf)
|
||||
{
|
||||
bool success = true; /* indicate here if the command ran ok or
|
||||
* failed */
|
||||
bool quiet = GetVariableBool(pset->vars, "quiet");
|
||||
bool quiet = QUIET();
|
||||
|
||||
backslashResult status = CMD_SKIP_LINE;
|
||||
|
||||
@ -291,16 +295,16 @@ exec_command(const char *cmd,
|
||||
/* \a -- toggle field alignment This makes little sense but we keep it around. */
|
||||
if (strcmp(cmd, "a") == 0)
|
||||
{
|
||||
if (pset->popt.topt.format != PRINT_ALIGNED)
|
||||
success = do_pset("format", "aligned", &pset->popt, quiet);
|
||||
if (pset.popt.topt.format != PRINT_ALIGNED)
|
||||
success = do_pset("format", "aligned", &pset.popt, quiet);
|
||||
else
|
||||
success = do_pset("format", "unaligned", &pset->popt, quiet);
|
||||
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);
|
||||
success = do_pset("title", options[0], &pset.popt, quiet);
|
||||
|
||||
|
||||
/*----------
|
||||
@ -316,25 +320,25 @@ exec_command(const char *cmd,
|
||||
{
|
||||
if (options[1])
|
||||
/* gave username */
|
||||
success = do_connect(options[0], options[1], pset);
|
||||
success = do_connect(options[0], options[1]);
|
||||
else
|
||||
{
|
||||
if (options[0])
|
||||
/* gave database name */
|
||||
success = do_connect(options[0], "", pset); /* empty string is same
|
||||
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, pset);
|
||||
success = do_connect(NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* \copy */
|
||||
else if (strcmp(cmd, "copy") == 0)
|
||||
success = do_copy(options_string, pset);
|
||||
else if (strcasecmp(cmd, "copy") == 0)
|
||||
success = do_copy(options_string);
|
||||
|
||||
/* \copyright */
|
||||
else if (strcmp(cmd, "copyright") == 0)
|
||||
@ -350,31 +354,31 @@ exec_command(const char *cmd,
|
||||
case '\0':
|
||||
case '?':
|
||||
if (options[0])
|
||||
success = describeTableDetails(options[0], pset, show_verbose);
|
||||
success = describeTableDetails(options[0], show_verbose);
|
||||
else
|
||||
/* standard listing of interesting things */
|
||||
success = listTables("tvs", NULL, pset, show_verbose);
|
||||
success = listTables("tvs", NULL, show_verbose);
|
||||
break;
|
||||
case 'a':
|
||||
success = describeAggregates(options[0], pset);
|
||||
success = describeAggregates(options[0]);
|
||||
break;
|
||||
case 'd':
|
||||
success = objectDescription(options[0], pset);
|
||||
success = objectDescription(options[0]);
|
||||
break;
|
||||
case 'f':
|
||||
success = describeFunctions(options[0], pset, show_verbose);
|
||||
success = describeFunctions(options[0], show_verbose);
|
||||
break;
|
||||
case 'l':
|
||||
success = do_lo_list(pset);
|
||||
success = do_lo_list();
|
||||
break;
|
||||
case 'o':
|
||||
success = describeOperators(options[0], pset);
|
||||
success = describeOperators(options[0]);
|
||||
break;
|
||||
case 'p':
|
||||
success = permissionsList(options[0], pset);
|
||||
success = permissionsList(options[0]);
|
||||
break;
|
||||
case 'T':
|
||||
success = describeTypes(options[0], pset, show_verbose);
|
||||
success = describeTypes(options[0], show_verbose);
|
||||
break;
|
||||
case 't':
|
||||
case 'v':
|
||||
@ -382,9 +386,9 @@ exec_command(const char *cmd,
|
||||
case 's':
|
||||
case 'S':
|
||||
if (cmd[1] == 'S' && cmd[2] == '\0')
|
||||
success = listTables("Stvs", NULL, pset, show_verbose);
|
||||
success = listTables("Stvs", NULL, show_verbose);
|
||||
else
|
||||
success = listTables(&cmd[1], options[0], pset, show_verbose);
|
||||
success = listTables(&cmd[1], options[0], show_verbose);
|
||||
break;
|
||||
default:
|
||||
status = CMD_UNKNOWN;
|
||||
@ -412,15 +416,15 @@ exec_command(const char *cmd,
|
||||
|
||||
/* \f -- change field separator */
|
||||
else if (strcmp(cmd, "f") == 0)
|
||||
success = do_pset("fieldsep", options[0], &pset->popt, quiet);
|
||||
success = do_pset("fieldsep", options[0], &pset.popt, quiet);
|
||||
|
||||
/* \g means send query */
|
||||
else if (strcmp(cmd, "g") == 0)
|
||||
{
|
||||
if (!options[0])
|
||||
pset->gfname = NULL;
|
||||
pset.gfname = NULL;
|
||||
else
|
||||
pset->gfname = xstrdup(options[0]);
|
||||
pset.gfname = xstrdup(options[0]);
|
||||
status = CMD_SEND;
|
||||
}
|
||||
|
||||
@ -442,10 +446,10 @@ exec_command(const char *cmd,
|
||||
/* HTML mode */
|
||||
else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
|
||||
{
|
||||
if (pset->popt.topt.format != PRINT_HTML)
|
||||
success = do_pset("format", "html", &pset->popt, quiet);
|
||||
if (pset.popt.topt.format != PRINT_HTML)
|
||||
success = do_pset("format", "html", &pset.popt, quiet);
|
||||
else
|
||||
success = do_pset("format", "aligned", &pset->popt, quiet);
|
||||
success = do_pset("format", "aligned", &pset.popt, quiet);
|
||||
}
|
||||
|
||||
|
||||
@ -454,22 +458,22 @@ exec_command(const char *cmd,
|
||||
{
|
||||
if (!options[0])
|
||||
{
|
||||
if (pset->cur_cmd_interactive)
|
||||
if (pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "\\%s: missing required argument\n", cmd);
|
||||
else
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
success = process_file(options[0], pset);
|
||||
success = process_file(options[0]);
|
||||
}
|
||||
|
||||
|
||||
/* \l is list databases */
|
||||
else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
|
||||
success = listAllDbs(pset, false);
|
||||
success = listAllDbs(false);
|
||||
else if (strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
|
||||
success = listAllDbs(pset, true);
|
||||
success = listAllDbs(true);
|
||||
|
||||
|
||||
/* large object things */
|
||||
@ -479,45 +483,45 @@ exec_command(const char *cmd,
|
||||
{
|
||||
if (!options[1])
|
||||
{
|
||||
if (pset->cur_cmd_interactive)
|
||||
if (pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "\\%s: missing required argument", cmd);
|
||||
else
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
success = do_lo_export(pset, options[0], options[1]);
|
||||
success = do_lo_export(options[0], options[1]);
|
||||
}
|
||||
|
||||
else if (strcmp(cmd + 3, "import") == 0)
|
||||
{
|
||||
if (!options[0])
|
||||
{
|
||||
if (pset->cur_cmd_interactive)
|
||||
if (pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "\\%s: missing required argument", cmd);
|
||||
else
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
success = do_lo_import(pset, options[0], options[1]);
|
||||
success = do_lo_import(options[0], options[1]);
|
||||
}
|
||||
|
||||
else if (strcmp(cmd + 3, "list") == 0)
|
||||
success = do_lo_list(pset);
|
||||
success = do_lo_list();
|
||||
|
||||
else if (strcmp(cmd + 3, "unlink") == 0)
|
||||
{
|
||||
if (!options[0])
|
||||
{
|
||||
if (pset->cur_cmd_interactive)
|
||||
if (pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "\\%s: missing required argument", cmd);
|
||||
else
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
success = do_lo_unlink(pset, options[0]);
|
||||
success = do_lo_unlink(options[0]);
|
||||
}
|
||||
|
||||
else
|
||||
@ -526,7 +530,7 @@ exec_command(const char *cmd,
|
||||
|
||||
/* \o -- set query output */
|
||||
else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
|
||||
success = setQFout(options[0], pset);
|
||||
success = setQFout(options[0]);
|
||||
|
||||
|
||||
/* \p prints the current query buffer */
|
||||
@ -544,14 +548,14 @@ exec_command(const char *cmd,
|
||||
{
|
||||
if (!options[0])
|
||||
{
|
||||
if (pset->cur_cmd_interactive)
|
||||
if (pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "\\%s: missing required argument", cmd);
|
||||
else
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
success = do_pset(options[0], options[1], &pset->popt, quiet);
|
||||
success = do_pset(options[0], options[1], &pset.popt, quiet);
|
||||
}
|
||||
|
||||
/* \q or \quit */
|
||||
@ -564,8 +568,8 @@ exec_command(const char *cmd,
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16 && options[i]; i++)
|
||||
fputs(options[i], pset->queryFout);
|
||||
fputs("\n", pset->queryFout);
|
||||
fputs(options[i], pset.queryFout);
|
||||
fputs("\n", pset.queryFout);
|
||||
}
|
||||
|
||||
/* reset(clear) the buffer */
|
||||
@ -607,18 +611,21 @@ exec_command(const char *cmd,
|
||||
*/
|
||||
struct _variable *ptr;
|
||||
|
||||
for (ptr = pset->vars; ptr->next; ptr = ptr->next)
|
||||
for (ptr = pset.vars; ptr->next; ptr = ptr->next)
|
||||
fprintf(stdout, "%s = '%s'\n", ptr->next->name, ptr->next->value);
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!SetVariable(pset->vars, options[0], options[1]))
|
||||
const char * val = options[1];
|
||||
if (!val)
|
||||
val = "";
|
||||
if (!SetVariable(pset.vars, options[0], val))
|
||||
{
|
||||
if (pset->cur_cmd_interactive)
|
||||
fprintf(stderr, "\\%s: failed\n", cmd);
|
||||
if (pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "\\%s: error\n", cmd);
|
||||
else
|
||||
fprintf(stderr, "%s: \\%s: failed\n", pset->progname, cmd);
|
||||
fprintf(stderr, "%s: \\%s: error\n", pset.progname, cmd);
|
||||
|
||||
success = false;
|
||||
}
|
||||
@ -627,13 +634,26 @@ exec_command(const char *cmd,
|
||||
|
||||
/* \t -- turn off headers and row count */
|
||||
else if (strcmp(cmd, "t") == 0)
|
||||
success = do_pset("tuples_only", NULL, &pset->popt, quiet);
|
||||
success = do_pset("tuples_only", NULL, &pset.popt, quiet);
|
||||
|
||||
|
||||
/* \T -- define html <table ...> attributes */
|
||||
else if (strcmp(cmd, "T") == 0)
|
||||
success = do_pset("tableattr", options[0], &pset->popt, quiet);
|
||||
success = do_pset("tableattr", options[0], &pset.popt, quiet);
|
||||
|
||||
/* \unset */
|
||||
else if (strcmp(cmd, "unset") == 0)
|
||||
{
|
||||
if (!SetVariable(pset.vars, options[0], NULL))
|
||||
{
|
||||
if (pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "\\%s: error\n", cmd);
|
||||
else
|
||||
fprintf(stderr, "%s: \\%s: error\n", pset.progname, cmd);
|
||||
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* \w -- write query buffer to file */
|
||||
else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
|
||||
@ -643,10 +663,10 @@ exec_command(const char *cmd,
|
||||
|
||||
if (!options[0])
|
||||
{
|
||||
if (pset->cur_cmd_interactive)
|
||||
if (pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "\\%s: missing required argument", cmd);
|
||||
else
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
|
||||
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
@ -698,19 +718,19 @@ exec_command(const char *cmd,
|
||||
|
||||
/* \x -- toggle expanded table representation */
|
||||
else if (strcmp(cmd, "x") == 0)
|
||||
success = do_pset("expanded", NULL, &pset->popt, quiet);
|
||||
success = do_pset("expanded", NULL, &pset.popt, quiet);
|
||||
|
||||
|
||||
/* list table rights (grant/revoke) */
|
||||
else if (strcmp(cmd, "z") == 0)
|
||||
success = permissionsList(options[0], pset);
|
||||
success = permissionsList(options[0]);
|
||||
|
||||
|
||||
else if (strcmp(cmd, "!") == 0)
|
||||
success = do_shell(options_string);
|
||||
|
||||
else if (strcmp(cmd, "?") == 0)
|
||||
slashUsage(pset);
|
||||
slashUsage();
|
||||
|
||||
|
||||
#ifdef NOT_USED
|
||||
@ -748,7 +768,7 @@ exec_command(const char *cmd,
|
||||
* The return value is malloc()'ed.
|
||||
*/
|
||||
static char *
|
||||
unescape(const char *source, PsqlSettings *pset)
|
||||
unescape(const char *source)
|
||||
{
|
||||
unsigned char *p;
|
||||
bool esc = false; /* Last character we saw was the escape
|
||||
@ -831,8 +851,9 @@ unescape(const char *source, PsqlSettings *pset)
|
||||
len = strcspn(p + 2, "}");
|
||||
copy = xstrdup(p + 2);
|
||||
copy[len] = '\0';
|
||||
value = interpolate_var(copy, pset);
|
||||
|
||||
value = GetVariable(pset.vars, copy);
|
||||
if (!value)
|
||||
value = "";
|
||||
length += strlen(value) - (len + 3);
|
||||
new = realloc(destination, length);
|
||||
if (!new)
|
||||
@ -871,40 +892,42 @@ unescape(const char *source, PsqlSettings *pset)
|
||||
*
|
||||
* Connects to a database (new_dbname) as a certain user (new_user).
|
||||
* The new user can be NULL. A db name of "-" is the same as the old one.
|
||||
* (That is, the one currently in pset. But pset->db can also be NULL. A NULL
|
||||
* (That is, the one currently in pset. But pset.db can also be NULL. A NULL
|
||||
* dbname is handled by libpq.)
|
||||
* Returns true if all ok, false if the new connection couldn't be established
|
||||
* but the old one was set back. Otherwise it terminates the program.
|
||||
*/
|
||||
static bool
|
||||
do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
|
||||
do_connect(const char *new_dbname, const char *new_user)
|
||||
{
|
||||
PGconn *oldconn = pset->db;
|
||||
PGconn *oldconn = pset.db;
|
||||
const char *dbparam = NULL;
|
||||
const char *userparam = NULL;
|
||||
const char *pwparam = NULL;
|
||||
char *prompted_password = NULL;
|
||||
char *prompted_user = NULL;
|
||||
bool need_pass;
|
||||
bool success = false;
|
||||
|
||||
/* Delete variables (in case we fail before setting them anew) */
|
||||
SetVariable(pset.vars, "DBNAME", NULL);
|
||||
SetVariable(pset.vars, "USER", NULL);
|
||||
SetVariable(pset.vars, "HOST", NULL);
|
||||
SetVariable(pset.vars, "PORT", NULL);
|
||||
|
||||
/* If dbname is "-" then use old name, else new one (even if NULL) */
|
||||
if (new_dbname && PQdb(oldconn) && (strcmp(new_dbname, "-") == 0 || strcmp(new_dbname, PQdb(oldconn)) == 0))
|
||||
if (oldconn && new_dbname && PQdb(oldconn) && strcmp(new_dbname, "-") == 0)
|
||||
dbparam = PQdb(oldconn);
|
||||
else
|
||||
dbparam = new_dbname;
|
||||
|
||||
/* If user is "" or "-" then use the old one */
|
||||
if (new_user && PQuser(oldconn) && (strcmp(new_user, "") == 0 || strcmp(new_user, "-") == 0 || strcmp(new_user, PQuser(oldconn)) == 0))
|
||||
/* If user is "" then use the old one */
|
||||
if (new_user && PQuser(oldconn) && strcmp(new_user, "")==0)
|
||||
userparam = PQuser(oldconn);
|
||||
/* If username is "?" then prompt */
|
||||
else if (new_user && strcmp(new_user, "?") == 0)
|
||||
userparam = prompted_user = simple_prompt("Username: ", 100, true); /* save for free() */
|
||||
else
|
||||
userparam = new_user;
|
||||
|
||||
/* need to prompt for password? */
|
||||
if (pset->getPassword)
|
||||
if (pset.getPassword)
|
||||
pwparam = prompted_password = simple_prompt("Password: ", 100, false); /* need to save for
|
||||
* free() */
|
||||
|
||||
@ -912,7 +935,7 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
|
||||
* Use old password if no new one given (if you didn't have an old
|
||||
* one, fine)
|
||||
*/
|
||||
if (!pwparam)
|
||||
if (!pwparam && oldconn)
|
||||
pwparam = PQpass(oldconn);
|
||||
|
||||
|
||||
@ -925,18 +948,18 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
|
||||
* the default PGCLIENTENCODING value. -- 1998/12/12 Tatsuo Ishii
|
||||
*/
|
||||
|
||||
if (!pset->has_client_encoding)
|
||||
if (!pset.has_client_encoding)
|
||||
putenv("PGCLIENTENCODING=");
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
need_pass = false;
|
||||
pset->db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
|
||||
pset.db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
|
||||
NULL, NULL, dbparam, userparam, pwparam);
|
||||
|
||||
if (PQstatus(pset->db) == CONNECTION_BAD &&
|
||||
strcmp(PQerrorMessage(pset->db), "fe_sendauth: no password supplied\n") == 0)
|
||||
if (PQstatus(pset.db) == CONNECTION_BAD &&
|
||||
strcmp(PQerrorMessage(pset.db), "fe_sendauth: no password supplied\n") == 0)
|
||||
{
|
||||
need_pass = true;
|
||||
free(prompted_password);
|
||||
@ -946,40 +969,39 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
|
||||
} while (need_pass);
|
||||
|
||||
free(prompted_password);
|
||||
free(prompted_user);
|
||||
|
||||
/*
|
||||
* If connection failed, try at least keep the old one. That's
|
||||
* probably more convenient than just kicking you out of the program.
|
||||
*/
|
||||
if (!pset->db || PQstatus(pset->db) == CONNECTION_BAD)
|
||||
if (!pset.db || PQstatus(pset.db) == CONNECTION_BAD)
|
||||
{
|
||||
if (pset->cur_cmd_interactive)
|
||||
if (pset.cur_cmd_interactive)
|
||||
{
|
||||
fprintf(stderr, "\\connect: %s", PQerrorMessage(pset->db));
|
||||
PQfinish(pset->db);
|
||||
fprintf(stderr, "%s", PQerrorMessage(pset.db));
|
||||
PQfinish(pset.db);
|
||||
if (oldconn)
|
||||
{
|
||||
fputs("Previous connection kept\n", stderr);
|
||||
pset->db = oldconn;
|
||||
pset.db = oldconn;
|
||||
}
|
||||
else
|
||||
pset->db = NULL;
|
||||
pset.db = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we don't want unpredictable things to
|
||||
* happen in scripting mode */
|
||||
fprintf(stderr, "%s: \\connect: %s", pset->progname, PQerrorMessage(pset->db));
|
||||
PQfinish(pset->db);
|
||||
fprintf(stderr, "%s: \\connect: %s", pset.progname, PQerrorMessage(pset.db));
|
||||
PQfinish(pset.db);
|
||||
if (oldconn)
|
||||
PQfinish(oldconn);
|
||||
pset->db = NULL;
|
||||
pset.db = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GetVariable(pset->vars, "quiet"))
|
||||
if (!QUIET())
|
||||
{
|
||||
if (userparam != new_user) /* no new user */
|
||||
printf("You are now connected to database %s.\n", dbparam);
|
||||
@ -987,7 +1009,7 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
|
||||
printf("You are now connected as new user %s.\n", new_user);
|
||||
else /* both new */
|
||||
printf("You are now connected to database %s as user %s.\n",
|
||||
PQdb(pset->db), PQuser(pset->db));
|
||||
PQdb(pset.db), PQuser(pset.db));
|
||||
}
|
||||
|
||||
if (oldconn)
|
||||
@ -996,6 +1018,12 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
|
||||
success = true;
|
||||
}
|
||||
|
||||
/* Update variables */
|
||||
SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
|
||||
SetVariable(pset.vars, "USER", PQuser(pset.db));
|
||||
SetVariable(pset.vars, "HOST", PQhost(pset.db));
|
||||
SetVariable(pset.vars, "PORT", PQport(pset.db));
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -1191,7 +1219,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
|
||||
* Handler for \i, but can be used for other things as well.
|
||||
*/
|
||||
bool
|
||||
process_file(const char *filename, PsqlSettings *pset)
|
||||
process_file(const char *filename)
|
||||
{
|
||||
FILE *fd;
|
||||
int result;
|
||||
@ -1207,11 +1235,13 @@ process_file(const char *filename, PsqlSettings *pset)
|
||||
|
||||
if (!fd)
|
||||
{
|
||||
if (!pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset.progname);
|
||||
perror(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = MainLoop(pset, fd);
|
||||
result = MainLoop(fd);
|
||||
fclose(fd);
|
||||
return (result == EXIT_SUCCESS);
|
||||
}
|
||||
|
@ -24,19 +24,18 @@ typedef enum _backslashResult
|
||||
|
||||
|
||||
|
||||
backslashResult HandleSlashCmds(PsqlSettings *pset,
|
||||
const char *line,
|
||||
backslashResult
|
||||
HandleSlashCmds(const char *line,
|
||||
PQExpBuffer query_buf,
|
||||
const char **end_of_cmd);
|
||||
|
||||
bool process_file(const char *filename,
|
||||
PsqlSettings *pset);
|
||||
bool
|
||||
process_file(const char *filename);
|
||||
|
||||
|
||||
bool do_pset(const char *param,
|
||||
bool
|
||||
do_pset(const char *param,
|
||||
const char *value,
|
||||
printQueryOpt * popt,
|
||||
bool quiet);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <config.h>
|
||||
#include <c.h>
|
||||
#include "common.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -12,7 +12,6 @@
|
||||
#include <strdup.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h> /* for write() */
|
||||
#else
|
||||
@ -73,64 +72,46 @@ xstrdup(const char *string)
|
||||
* Upon failure, sets stdout and returns false.
|
||||
*/
|
||||
bool
|
||||
setQFout(const char *fname, PsqlSettings *pset)
|
||||
setQFout(const char *fname)
|
||||
{
|
||||
bool status = true;
|
||||
|
||||
#ifdef USE_ASSERT_CHECKING
|
||||
assert(pset);
|
||||
#else
|
||||
if (!pset)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
/* Close old file/pipe */
|
||||
if (pset->queryFout && pset->queryFout != stdout && pset->queryFout != stderr)
|
||||
if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
|
||||
{
|
||||
if (pset->queryFoutPipe)
|
||||
pclose(pset->queryFout);
|
||||
if (pset.queryFoutPipe)
|
||||
pclose(pset.queryFout);
|
||||
else
|
||||
fclose(pset->queryFout);
|
||||
fclose(pset.queryFout);
|
||||
}
|
||||
|
||||
/* If no filename, set stdout */
|
||||
if (!fname || fname[0] == '\0')
|
||||
{
|
||||
pset->queryFout = stdout;
|
||||
pset->queryFoutPipe = false;
|
||||
pset.queryFout = stdout;
|
||||
pset.queryFoutPipe = false;
|
||||
}
|
||||
else if (*fname == '|')
|
||||
{
|
||||
const char *pipename = fname + 1;
|
||||
|
||||
|
||||
#ifndef __CYGWIN32__
|
||||
pset->queryFout = popen(pipename, "w");
|
||||
#else
|
||||
pset->queryFout = popen(pipename, "wb");
|
||||
#endif
|
||||
pset->queryFoutPipe = true;
|
||||
pset.queryFout = popen(fname + 1, "w");
|
||||
pset.queryFoutPipe = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef __CYGWIN32__
|
||||
pset->queryFout = fopen(fname, "w");
|
||||
#else
|
||||
pset->queryFout = fopen(fname, "wb");
|
||||
#endif
|
||||
pset->queryFoutPipe = false;
|
||||
pset.queryFout = fopen(fname, "w");
|
||||
pset.queryFoutPipe = false;
|
||||
}
|
||||
|
||||
if (!pset->queryFout)
|
||||
if (!(pset.queryFout))
|
||||
{
|
||||
perror(fname);
|
||||
pset->queryFout = stdout;
|
||||
pset->queryFoutPipe = false;
|
||||
fprintf(stderr, "%s: %s: %s\n", pset.progname, fname, strerror(errno));
|
||||
pset.queryFout = stdout;
|
||||
pset.queryFoutPipe = false;
|
||||
status = false;
|
||||
}
|
||||
|
||||
/* Direct signals */
|
||||
if (pset->queryFoutPipe)
|
||||
if (pset.queryFoutPipe)
|
||||
pqsignal(SIGPIPE, SIG_IGN);
|
||||
else
|
||||
pqsignal(SIGPIPE, SIG_DFL);
|
||||
@ -211,93 +192,6 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* interpolate_var()
|
||||
*
|
||||
* The idea here is that certain variables have a "magic" meaning, such as
|
||||
* LastOid. However, you can assign to those variables, but that will shadow
|
||||
* the magic meaning, until you unset it. If nothing matches, the value of
|
||||
* the environment variable is used.
|
||||
*
|
||||
* This function only returns NULL if you feed in NULL's (don't do that).
|
||||
* Otherwise, the return value is ready for immediate consumption.
|
||||
*/
|
||||
const char *
|
||||
interpolate_var(const char *name, PsqlSettings *pset)
|
||||
{
|
||||
const char *var;
|
||||
|
||||
#ifdef USE_ASSERT_CHECKING
|
||||
assert(name);
|
||||
assert(pset);
|
||||
#else
|
||||
if (!name || !pset)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
var = GetVariable(pset->vars, name);
|
||||
if (var)
|
||||
return var;
|
||||
|
||||
/* otherwise return magic variable */
|
||||
|
||||
/*
|
||||
* (by convention these should be capitalized (but not all caps), to
|
||||
* not be shadowed by regular vars or to shadow env vars)
|
||||
*/
|
||||
if (strcmp(name, "Version") == 0)
|
||||
return PG_VERSION_STR;
|
||||
|
||||
if (strcmp(name, "Database") == 0)
|
||||
{
|
||||
if (PQdb(pset->db))
|
||||
return PQdb(pset->db);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
if (strcmp(name, "User") == 0)
|
||||
{
|
||||
if (PQuser(pset->db))
|
||||
return PQuser(pset->db);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
if (strcmp(name, "Host") == 0)
|
||||
{
|
||||
if (PQhost(pset->db))
|
||||
return PQhost(pset->db);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
if (strcmp(name, "Port") == 0)
|
||||
{
|
||||
if (PQport(pset->db))
|
||||
return PQport(pset->db);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
if (strcmp(name, "LastOid") == 0)
|
||||
{
|
||||
static char buf[24];
|
||||
if (pset->lastOid == InvalidOid)
|
||||
return "";
|
||||
sprintf(buf, "%u", pset->lastOid);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* env vars */
|
||||
if ((var = getenv(name)))
|
||||
return var;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Code to support query cancellation
|
||||
*
|
||||
@ -333,21 +227,21 @@ handle_sigint(SIGNAL_ARGS)
|
||||
* PSQLexec
|
||||
*
|
||||
* This is the way to send "backdoor" queries (those not directly entered
|
||||
* by the user). It is subject to -E (echo_secret) but not -e (echo).
|
||||
* by the user). It is subject to -E but not -e.
|
||||
*/
|
||||
PGresult *
|
||||
PSQLexec(PsqlSettings *pset, const char *query)
|
||||
PSQLexec(const char *query)
|
||||
{
|
||||
PGresult *res;
|
||||
const char *var;
|
||||
|
||||
if (!pset->db)
|
||||
if (!pset.db)
|
||||
{
|
||||
fputs("You are currently not connected to a database.\n", stderr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
var = GetVariable(pset->vars, "echo_secret");
|
||||
var = GetVariable(pset.vars, "ECHO_HIDDEN");
|
||||
if (var)
|
||||
{
|
||||
printf("********* QUERY *********\n%s\n*************************\n\n", query);
|
||||
@ -357,50 +251,50 @@ PSQLexec(PsqlSettings *pset, const char *query)
|
||||
if (var && strcmp(var, "noexec") == 0)
|
||||
return NULL;
|
||||
|
||||
cancelConn = pset->db;
|
||||
cancelConn = pset.db;
|
||||
pqsignal(SIGINT, handle_sigint); /* control-C => cancel */
|
||||
|
||||
res = PQexec(pset->db, query);
|
||||
res = PQexec(pset.db, query);
|
||||
|
||||
pqsignal(SIGINT, SIG_DFL); /* now control-C is back to normal */
|
||||
|
||||
if (PQstatus(pset->db) == CONNECTION_OK)
|
||||
if (PQstatus(pset.db) == CONNECTION_BAD)
|
||||
{
|
||||
if (!pset.cur_cmd_interactive)
|
||||
{
|
||||
fprintf(stderr, "%s: connection to server was lost", pset.progname);
|
||||
exit(EXIT_BADCONN);
|
||||
}
|
||||
fputs("The connection to the server was lost. Attempting reset: ", stderr);
|
||||
PQreset(pset.db);
|
||||
if (PQstatus(pset.db) == CONNECTION_BAD)
|
||||
{
|
||||
fputs("Failed.\n", stderr);
|
||||
PQfinish(pset.db);
|
||||
PQclear(res);
|
||||
pset.db = NULL;
|
||||
SetVariable(pset.vars, "DBNAME", NULL);
|
||||
SetVariable(pset.vars, "HOST", NULL);
|
||||
SetVariable(pset.vars, "PORT", NULL);
|
||||
SetVariable(pset.vars, "USER", NULL);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
fputs("Succeeded.\n", stderr);
|
||||
}
|
||||
|
||||
if (res && (PQresultStatus(res) == PGRES_COMMAND_OK ||
|
||||
PQresultStatus(res) == PGRES_TUPLES_OK ||
|
||||
PQresultStatus(res) == PGRES_COPY_IN ||
|
||||
PQresultStatus(res) == PGRES_COPY_OUT)
|
||||
)
|
||||
return res; /* Normal success case... */
|
||||
/* Normal failure case --- display error and return NULL */
|
||||
fputs(PQerrorMessage(pset->db), pset->queryFout);
|
||||
PQclear(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Lost connection. Report whatever libpq has to say,
|
||||
* then consider recovery.
|
||||
*/
|
||||
fputs(PQerrorMessage(pset->db), pset->queryFout);
|
||||
PQclear(res);
|
||||
if (!pset->cur_cmd_interactive)
|
||||
{
|
||||
fprintf(stderr, "%s: connection to server was lost\n",
|
||||
pset->progname);
|
||||
exit(EXIT_BADCONN);
|
||||
}
|
||||
fputs("The connection to the server was lost. Attempting reset: ", stderr);
|
||||
fflush(stderr);
|
||||
PQreset(pset->db);
|
||||
if (PQstatus(pset->db) == CONNECTION_BAD)
|
||||
{
|
||||
fputs("Failed.\n", stderr);
|
||||
PQfinish(pset->db);
|
||||
pset->db = NULL;
|
||||
}
|
||||
return res;
|
||||
else
|
||||
fputs("Succeeded.\n", stderr);
|
||||
{
|
||||
fputs(PQerrorMessage(pset.db), stderr);
|
||||
PQclear(res);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -418,19 +312,19 @@ PSQLexec(PsqlSettings *pset, const char *query)
|
||||
* Returns true if the query executed successfully, false otherwise.
|
||||
*/
|
||||
bool
|
||||
SendQuery(PsqlSettings *pset, const char *query)
|
||||
SendQuery(const char *query)
|
||||
{
|
||||
bool success = false;
|
||||
PGresult *results;
|
||||
PGnotify *notify;
|
||||
|
||||
if (!pset->db)
|
||||
if (!pset.db)
|
||||
{
|
||||
fputs("You are currently not connected to a database.\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetVariableBool(pset->vars, "singlestep"))
|
||||
if (GetVariableBool(pset.vars, "SINGLESTEP"))
|
||||
{
|
||||
char buf[3];
|
||||
|
||||
@ -443,17 +337,23 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||
if (buf[0] == 'x')
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char * var = GetVariable(pset.vars, "ECHO");
|
||||
if (var && strcmp(var, "brief")==0)
|
||||
puts(query);
|
||||
}
|
||||
|
||||
cancelConn = pset->db;
|
||||
cancelConn = pset.db;
|
||||
pqsignal(SIGINT, handle_sigint);
|
||||
|
||||
results = PQexec(pset->db, query);
|
||||
results = PQexec(pset.db, query);
|
||||
|
||||
pqsignal(SIGINT, SIG_DFL);
|
||||
|
||||
if (results == NULL)
|
||||
{
|
||||
fputs(PQerrorMessage(pset->db), pset->queryFout);
|
||||
fputs(PQerrorMessage(pset.db), pset.queryFout);
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
@ -461,24 +361,30 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||
switch (PQresultStatus(results))
|
||||
{
|
||||
case PGRES_TUPLES_OK:
|
||||
if (pset->gfname)
|
||||
/* write output to \g argument, if any */
|
||||
if (pset.gfname)
|
||||
{
|
||||
PsqlSettings settings_copy = *pset;
|
||||
FILE * queryFout_copy = pset.queryFout;
|
||||
bool queryFoutPipe_copy = pset.queryFoutPipe;
|
||||
pset.queryFout = NULL; /* so it doesn't get closed */
|
||||
|
||||
settings_copy.queryFout = stdout;
|
||||
if (!setQFout(pset->gfname, &settings_copy))
|
||||
/* open file/pipe */
|
||||
if (!setQFout(pset.gfname))
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
printQuery(results, &settings_copy.popt, settings_copy.queryFout);
|
||||
printQuery(results, &pset.popt, pset.queryFout);
|
||||
|
||||
/* close file/pipe */
|
||||
setQFout(NULL, &settings_copy);
|
||||
setQFout(NULL);
|
||||
|
||||
free(pset->gfname);
|
||||
pset->gfname = NULL;
|
||||
free(pset.gfname);
|
||||
pset.gfname = NULL;
|
||||
|
||||
pset.queryFout = queryFout_copy;
|
||||
pset.queryFoutPipe = queryFoutPipe_copy;
|
||||
|
||||
success = true;
|
||||
break;
|
||||
@ -486,59 +392,65 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||
else
|
||||
{
|
||||
success = true;
|
||||
printQuery(results, &pset->popt, pset->queryFout);
|
||||
printQuery(results, &pset.popt, pset.queryFout);
|
||||
}
|
||||
break;
|
||||
case PGRES_EMPTY_QUERY:
|
||||
success = true;
|
||||
break;
|
||||
case PGRES_COMMAND_OK:
|
||||
success = true;
|
||||
pset->lastOid = PQoidValue(results);
|
||||
if (!GetVariableBool(pset->vars, "quiet"))
|
||||
fprintf(pset->queryFout, "%s\n", PQcmdStatus(results));
|
||||
break;
|
||||
{
|
||||
char buf[10];
|
||||
|
||||
success = true;
|
||||
sprintf(buf, "%u", (unsigned int)PQoidValue(results));
|
||||
if (!QUIET())
|
||||
fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
|
||||
SetVariable(pset.vars, "LASTOID", buf);
|
||||
break;
|
||||
}
|
||||
case PGRES_COPY_OUT:
|
||||
success = handleCopyOut(pset->db, pset->queryFout);
|
||||
success = handleCopyOut(pset.db, pset.queryFout);
|
||||
break;
|
||||
|
||||
case PGRES_COPY_IN:
|
||||
if (pset->cur_cmd_interactive && !GetVariable(pset->vars, "quiet"))
|
||||
if (pset.cur_cmd_interactive && !QUIET())
|
||||
puts("Enter data to be copied followed by a newline.\n"
|
||||
"End with a backslash and a period on a line by itself.");
|
||||
|
||||
success = handleCopyIn(pset->db, pset->cur_cmd_source,
|
||||
pset->cur_cmd_interactive ? get_prompt(pset, PROMPT_COPY) : NULL);
|
||||
success = handleCopyIn(pset.db, pset.cur_cmd_source,
|
||||
pset.cur_cmd_interactive ? get_prompt(PROMPT_COPY) : NULL);
|
||||
break;
|
||||
|
||||
case PGRES_NONFATAL_ERROR:
|
||||
case PGRES_FATAL_ERROR:
|
||||
case PGRES_BAD_RESPONSE:
|
||||
success = false;
|
||||
fputs(PQerrorMessage(pset->db), stderr);
|
||||
fputs(PQerrorMessage(pset.db), stderr);
|
||||
break;
|
||||
}
|
||||
|
||||
fflush(pset->queryFout);
|
||||
fflush(pset.queryFout);
|
||||
|
||||
if (PQstatus(pset->db) == CONNECTION_BAD)
|
||||
if (PQstatus(pset.db) == CONNECTION_BAD)
|
||||
{
|
||||
if (!pset->cur_cmd_interactive)
|
||||
if (!pset.cur_cmd_interactive)
|
||||
{
|
||||
fprintf(stderr, "%s: connection to server was lost\n",
|
||||
pset->progname);
|
||||
fprintf(stderr, "%s: connection to server was lost", pset.progname);
|
||||
exit(EXIT_BADCONN);
|
||||
}
|
||||
fputs("The connection to the server was lost. Attempting reset: ", stderr);
|
||||
fflush(stderr);
|
||||
PQreset(pset->db);
|
||||
if (PQstatus(pset->db) == CONNECTION_BAD)
|
||||
PQreset(pset.db);
|
||||
if (PQstatus(pset.db) == CONNECTION_BAD)
|
||||
{
|
||||
fputs("Failed.\n", stderr);
|
||||
PQfinish(pset->db);
|
||||
pset->db = NULL;
|
||||
PQfinish(pset.db);
|
||||
PQclear(results);
|
||||
pset.db = NULL;
|
||||
SetVariable(pset.vars, "DBNAME", NULL);
|
||||
SetVariable(pset.vars, "HOST", NULL);
|
||||
SetVariable(pset.vars, "PORT", NULL);
|
||||
SetVariable(pset.vars, "USER", NULL);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@ -546,12 +458,12 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||
}
|
||||
|
||||
/* check for asynchronous notification returns */
|
||||
while ((notify = PQnotifies(pset->db)) != NULL)
|
||||
while ((notify = PQnotifies(pset.db)) != NULL)
|
||||
{
|
||||
fprintf(pset->queryFout, "Asynchronous NOTIFY '%s' from backend with pid '%d' received.\n",
|
||||
fprintf(pset.queryFout, "Asynchronous NOTIFY '%s' from backend with pid '%d' received.\n",
|
||||
notify->relname, notify->be_pid);
|
||||
free(notify);
|
||||
fflush(pset->queryFout);
|
||||
fflush(pset.queryFout);
|
||||
}
|
||||
|
||||
if (results)
|
||||
|
@ -8,18 +8,15 @@ char *
|
||||
xstrdup(const char *string);
|
||||
|
||||
bool
|
||||
setQFout(const char *fname, PsqlSettings *pset);
|
||||
setQFout(const char *fname);
|
||||
|
||||
char *
|
||||
simple_prompt(const char *prompt, int maxlen, bool echo);
|
||||
|
||||
const char *
|
||||
interpolate_var(const char *name, PsqlSettings *pset);
|
||||
|
||||
PGresult *
|
||||
PSQLexec(PsqlSettings *pset, const char *query);
|
||||
PSQLexec(const char *query);
|
||||
|
||||
bool
|
||||
SendQuery(PsqlSettings *pset, const char *query);
|
||||
SendQuery(const char *query);
|
||||
|
||||
#endif /* COMMON_H */
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <config.h>
|
||||
#include <c.h>
|
||||
#include "copy.h"
|
||||
|
||||
@ -36,7 +35,7 @@
|
||||
struct copy_options
|
||||
{
|
||||
char *table;
|
||||
char *file;
|
||||
char *file; /* NULL = stdin/stdout */
|
||||
bool from;
|
||||
bool binary;
|
||||
bool oids;
|
||||
@ -59,7 +58,7 @@ free_copy_options(struct copy_options * ptr)
|
||||
|
||||
|
||||
static struct copy_options *
|
||||
parse_slash_copy(const char *args, PsqlSettings *pset)
|
||||
parse_slash_copy(const char *args)
|
||||
{
|
||||
struct copy_options *result;
|
||||
char *line;
|
||||
@ -132,17 +131,15 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
|
||||
|
||||
if (!error)
|
||||
{
|
||||
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
|
||||
token = strtokx(NULL, " \t", "'", '\\', "e, NULL);
|
||||
if (!token)
|
||||
error = true;
|
||||
else if (!quote && (strcasecmp(token, "stdin")==0 || strcasecmp(token, "stdout")==0))
|
||||
result->file = NULL;
|
||||
else
|
||||
result->file = xstrdup(token);
|
||||
}
|
||||
|
||||
#ifdef USE_ASSERT_CHECKING
|
||||
assert(error || result->file);
|
||||
#endif
|
||||
|
||||
if (!error)
|
||||
{
|
||||
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
||||
@ -194,8 +191,8 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (!pset->cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset->progname);
|
||||
if (!pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset.progname);
|
||||
fputs("\\copy: parse error at ", stderr);
|
||||
if (!token)
|
||||
fputs("end of line", stderr);
|
||||
@ -217,7 +214,7 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
|
||||
* file or route its response into the file.
|
||||
*/
|
||||
bool
|
||||
do_copy(const char *args, PsqlSettings *pset)
|
||||
do_copy(const char *args)
|
||||
{
|
||||
char query[128 + NAMEDATALEN];
|
||||
FILE *copystream;
|
||||
@ -226,7 +223,7 @@ do_copy(const char *args, PsqlSettings *pset)
|
||||
bool success;
|
||||
|
||||
/* parse options */
|
||||
options = parse_slash_copy(args, pset);
|
||||
options = parse_slash_copy(args);
|
||||
|
||||
if (!options)
|
||||
return false;
|
||||
@ -242,9 +239,9 @@ do_copy(const char *args, PsqlSettings *pset)
|
||||
strcat(query, "WITH OIDS ");
|
||||
|
||||
if (options->from)
|
||||
strcat(query, "FROM stdin");
|
||||
strcat(query, "FROM STDIN");
|
||||
else
|
||||
strcat(query, "TO stdout");
|
||||
strcat(query, "TO STDOUT");
|
||||
|
||||
|
||||
if (options->delim)
|
||||
@ -254,24 +251,32 @@ do_copy(const char *args, PsqlSettings *pset)
|
||||
strcat(query, "'");
|
||||
}
|
||||
|
||||
if (options->null)
|
||||
{
|
||||
strcat(query, " WITH NULL AS '");
|
||||
strcat(query, options->null);
|
||||
strcat(query, "'");
|
||||
}
|
||||
|
||||
if (options->from)
|
||||
#ifndef __CYGWIN32__
|
||||
{
|
||||
if (options->file)
|
||||
copystream = fopen(options->file, "r");
|
||||
#else
|
||||
copystream = fopen(options->file, "rb");
|
||||
#endif
|
||||
else
|
||||
#ifndef __CYGWIN32__
|
||||
copystream = stdin;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (options->file)
|
||||
copystream = fopen(options->file, "w");
|
||||
#else
|
||||
copystream = fopen(options->file, "wb");
|
||||
#endif
|
||||
else
|
||||
copystream = stdout;
|
||||
}
|
||||
|
||||
if (!copystream)
|
||||
{
|
||||
if (!pset->cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset->progname);
|
||||
if (!pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset.progname);
|
||||
fprintf(stderr,
|
||||
"unable to open file %s: %s\n",
|
||||
options->file, strerror(errno));
|
||||
@ -279,39 +284,39 @@ do_copy(const char *args, PsqlSettings *pset)
|
||||
return false;
|
||||
}
|
||||
|
||||
result = PSQLexec(pset, query);
|
||||
result = PSQLexec(query);
|
||||
|
||||
switch (PQresultStatus(result))
|
||||
{
|
||||
case PGRES_COPY_OUT:
|
||||
success = handleCopyOut(pset->db, copystream);
|
||||
success = handleCopyOut(pset.db, copystream);
|
||||
break;
|
||||
case PGRES_COPY_IN:
|
||||
success = handleCopyIn(pset->db, copystream, NULL);
|
||||
success = handleCopyIn(pset.db, copystream, NULL);
|
||||
break;
|
||||
case PGRES_NONFATAL_ERROR:
|
||||
case PGRES_FATAL_ERROR:
|
||||
case PGRES_BAD_RESPONSE:
|
||||
success = false;
|
||||
fputs(PQerrorMessage(pset->db), stderr);
|
||||
fputs(PQerrorMessage(pset.db), stderr);
|
||||
break;
|
||||
default:
|
||||
success = false;
|
||||
if (!pset->cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset->progname);
|
||||
if (!pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset.progname);
|
||||
fprintf(stderr, "\\copy: unexpected response (%d)\n", PQresultStatus(result));
|
||||
}
|
||||
|
||||
PQclear(result);
|
||||
|
||||
if (!GetVariable(pset->vars, "quiet"))
|
||||
if (!success)
|
||||
{
|
||||
if (success)
|
||||
puts("Successfully copied");
|
||||
else
|
||||
puts("Copy failed");
|
||||
if (!pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset.progname);
|
||||
fprintf(stderr, "\\copy failed\n");
|
||||
}
|
||||
|
||||
if (copystream != stdout && copystream != stdin)
|
||||
fclose(copystream);
|
||||
free_copy_options(options);
|
||||
return success;
|
||||
@ -396,7 +401,7 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
|
||||
|
||||
while (!copydone)
|
||||
{ /* for each input line ... */
|
||||
if (prompt && isatty(fileno(stdin)))
|
||||
if (prompt && isatty(fileno(copystream)))
|
||||
{
|
||||
fputs(prompt, stdout);
|
||||
fflush(stdout);
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
/* handler for \copy */
|
||||
bool
|
||||
do_copy(const char *args, PsqlSettings *pset);
|
||||
do_copy(const char *args);
|
||||
|
||||
|
||||
/* lower level processors for copy in/out streams */
|
||||
|
@ -31,11 +31,11 @@
|
||||
* takes an optional regexp to match specific aggregates by name
|
||||
*/
|
||||
bool
|
||||
describeAggregates(const char *name, PsqlSettings *pset)
|
||||
describeAggregates(const char *name)
|
||||
{
|
||||
char buf[384 + 2 * REGEXP_CUTOFF];
|
||||
PGresult *res;
|
||||
printQueryOpt myopt = pset->popt;
|
||||
printQueryOpt myopt = pset.popt;
|
||||
|
||||
/*
|
||||
* There are two kinds of aggregates: ones that work on particular
|
||||
@ -72,14 +72,14 @@ describeAggregates(const char *name, PsqlSettings *pset)
|
||||
|
||||
strcat(buf, "ORDER BY \"Name\", \"Type\"");
|
||||
|
||||
res = PSQLexec(pset, buf);
|
||||
res = PSQLexec(buf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
myopt.nullPrint = NULL;
|
||||
myopt.title = "List of aggregates";
|
||||
|
||||
printQuery(res, &myopt, pset->queryFout);
|
||||
printQuery(res, &myopt, pset.queryFout);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -90,11 +90,11 @@ describeAggregates(const char *name, PsqlSettings *pset)
|
||||
* Takes an optional regexp to narrow down the function name
|
||||
*/
|
||||
bool
|
||||
describeFunctions(const char *name, PsqlSettings *pset, bool verbose)
|
||||
describeFunctions(const char *name, bool verbose)
|
||||
{
|
||||
char buf[384 + REGEXP_CUTOFF];
|
||||
PGresult *res;
|
||||
printQueryOpt myopt = pset->popt;
|
||||
printQueryOpt myopt = pset.popt;
|
||||
|
||||
/*
|
||||
* we skip in/out funcs by excluding functions that take some
|
||||
@ -125,14 +125,14 @@ describeFunctions(const char *name, PsqlSettings *pset, bool verbose)
|
||||
}
|
||||
strcat(buf, "ORDER BY \"Function\", \"Result\", \"Arguments\"");
|
||||
|
||||
res = PSQLexec(pset, buf);
|
||||
res = PSQLexec(buf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
myopt.nullPrint = NULL;
|
||||
myopt.title = "List of functions";
|
||||
|
||||
printQuery(res, &myopt, pset->queryFout);
|
||||
printQuery(res, &myopt, pset.queryFout);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -145,11 +145,11 @@ describeFunctions(const char *name, PsqlSettings *pset, bool verbose)
|
||||
* describe types
|
||||
*/
|
||||
bool
|
||||
describeTypes(const char *name, PsqlSettings *pset, bool verbose)
|
||||
describeTypes(const char *name, bool verbose)
|
||||
{
|
||||
char buf[256 + REGEXP_CUTOFF];
|
||||
PGresult *res;
|
||||
printQueryOpt myopt = pset->popt;
|
||||
printQueryOpt myopt = pset.popt;
|
||||
|
||||
strcpy(buf, "SELECT t.typname AS \"Type\"");
|
||||
if (verbose)
|
||||
@ -169,14 +169,14 @@ describeTypes(const char *name, PsqlSettings *pset, bool verbose)
|
||||
}
|
||||
strcat(buf, "ORDER BY t.typname;");
|
||||
|
||||
res = PSQLexec(pset, buf);
|
||||
res = PSQLexec(buf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
myopt.nullPrint = NULL;
|
||||
myopt.title = "List of types";
|
||||
|
||||
printQuery(res, &myopt, pset->queryFout);
|
||||
printQuery(res, &myopt, pset.queryFout);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -187,11 +187,11 @@ describeTypes(const char *name, PsqlSettings *pset, bool verbose)
|
||||
/* \do
|
||||
*/
|
||||
bool
|
||||
describeOperators(const char *name, PsqlSettings *pset)
|
||||
describeOperators(const char *name)
|
||||
{
|
||||
char buf[1536 + 3 * REGEXP_CUTOFF];
|
||||
PGresult *res;
|
||||
printQueryOpt myopt = pset->popt;
|
||||
printQueryOpt myopt = pset.popt;
|
||||
|
||||
strcpy(buf,
|
||||
"SELECT o.oprname AS \"Op\",\n"
|
||||
@ -251,14 +251,14 @@ describeOperators(const char *name, PsqlSettings *pset)
|
||||
}
|
||||
strcat(buf, "\nORDER BY \"Op\", \"Left arg\", \"Right arg\", \"Result\"");
|
||||
|
||||
res = PSQLexec(pset, buf);
|
||||
res = PSQLexec(buf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
myopt.nullPrint = NULL;
|
||||
myopt.title = "List of operators";
|
||||
|
||||
printQuery(res, &myopt, pset->queryFout);
|
||||
printQuery(res, &myopt, pset.queryFout);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -271,11 +271,11 @@ describeOperators(const char *name, PsqlSettings *pset)
|
||||
* for \l, \list, and -l switch
|
||||
*/
|
||||
bool
|
||||
listAllDbs(PsqlSettings *pset, bool desc)
|
||||
listAllDbs(bool desc)
|
||||
{
|
||||
PGresult *res;
|
||||
char buf[512];
|
||||
printQueryOpt myopt = pset->popt;
|
||||
printQueryOpt myopt = pset.popt;
|
||||
|
||||
strcpy(buf,
|
||||
"SELECT pg_database.datname as \"Database\",\n"
|
||||
@ -306,14 +306,14 @@ listAllDbs(PsqlSettings *pset, bool desc)
|
||||
|
||||
strcat(buf, "ORDER BY \"Database\"");
|
||||
|
||||
res = PSQLexec(pset, buf);
|
||||
res = PSQLexec(buf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
myopt.nullPrint = NULL;
|
||||
myopt.title = "List of databases";
|
||||
|
||||
printQuery(res, &myopt, pset->queryFout);
|
||||
printQuery(res, &myopt, pset.queryFout);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -325,11 +325,11 @@ listAllDbs(PsqlSettings *pset, bool desc)
|
||||
*
|
||||
*/
|
||||
bool
|
||||
permissionsList(const char *name, PsqlSettings *pset)
|
||||
permissionsList(const char *name)
|
||||
{
|
||||
char descbuf[256 + REGEXP_CUTOFF];
|
||||
PGresult *res;
|
||||
printQueryOpt myopt = pset->popt;
|
||||
printQueryOpt myopt = pset.popt;
|
||||
|
||||
descbuf[0] = '\0';
|
||||
/* Currently, we ignore indexes since they have no meaningful rights */
|
||||
@ -346,15 +346,15 @@ permissionsList(const char *name, PsqlSettings *pset)
|
||||
}
|
||||
strcat(descbuf, "ORDER BY relname");
|
||||
|
||||
res = PSQLexec(pset, descbuf);
|
||||
res = PSQLexec(descbuf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
myopt.nullPrint = NULL;
|
||||
sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset->db));
|
||||
sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset.db));
|
||||
myopt.title = descbuf;
|
||||
|
||||
printQuery(res, &myopt, pset->queryFout);
|
||||
printQuery(res, &myopt, pset.queryFout);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -371,11 +371,11 @@ permissionsList(const char *name, PsqlSettings *pset)
|
||||
* lists of things, there are other \d? commands.
|
||||
*/
|
||||
bool
|
||||
objectDescription(const char *object, PsqlSettings *pset)
|
||||
objectDescription(const char *object)
|
||||
{
|
||||
char descbuf[2048 + 7 * REGEXP_CUTOFF];
|
||||
PGresult *res;
|
||||
printQueryOpt myopt = pset->popt;
|
||||
printQueryOpt myopt = pset.popt;
|
||||
|
||||
descbuf[0] = '\0';
|
||||
|
||||
@ -466,7 +466,7 @@ objectDescription(const char *object, PsqlSettings *pset)
|
||||
strcat(descbuf, "\nORDER BY \"Name\"");
|
||||
|
||||
|
||||
res = PSQLexec(pset, descbuf);
|
||||
res = PSQLexec(descbuf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
@ -474,7 +474,7 @@ objectDescription(const char *object, PsqlSettings *pset)
|
||||
myopt.nullPrint = NULL;
|
||||
myopt.title = "Object descriptions";
|
||||
|
||||
printQuery(res, &myopt, pset->queryFout);
|
||||
printQuery(res, &myopt, pset.queryFout);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
@ -507,11 +507,11 @@ xmalloc(size_t size)
|
||||
|
||||
|
||||
bool
|
||||
describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
describeTableDetails(const char *name, bool desc)
|
||||
{
|
||||
char buf[512 + INDEX_MAX_KEYS * NAMEDATALEN];
|
||||
PGresult *res = NULL;
|
||||
printTableOpt myopt = pset->popt.topt;
|
||||
printTableOpt myopt = pset.popt.topt;
|
||||
int i;
|
||||
const char *view_def = NULL;
|
||||
const char *headers[5];
|
||||
@ -536,14 +536,14 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
"SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules\n"
|
||||
"FROM pg_class WHERE relname='%s'",
|
||||
name);
|
||||
res = PSQLexec(pset, buf);
|
||||
res = PSQLexec(buf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
/* Did we get anything? */
|
||||
if (PQntuples(res) == 0)
|
||||
{
|
||||
if (!GetVariableBool(pset->vars, "quiet"))
|
||||
if (!QUIET())
|
||||
fprintf(stderr, "Did not find any relation named \"%s\".\n", name);
|
||||
PQclear(res);
|
||||
return false;
|
||||
@ -587,7 +587,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
strcat(buf, "'\n AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid\n"
|
||||
"ORDER BY a.attnum");
|
||||
|
||||
res = PSQLexec(pset, buf);
|
||||
res = PSQLexec(buf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
@ -595,7 +595,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
if (tableinfo.hasrules) {
|
||||
PGresult *result;
|
||||
sprintf(buf, "SELECT definition FROM pg_views WHERE viewname = '%s'", name);
|
||||
result = PSQLexec(pset, buf);
|
||||
result = PSQLexec(buf);
|
||||
if (!result)
|
||||
{
|
||||
PQclear(res);
|
||||
@ -655,7 +655,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
"WHERE c.relname = '%s' AND c.oid = d.adrelid AND d.adnum = %s",
|
||||
name, PQgetvalue(res, i, 6));
|
||||
|
||||
result = PSQLexec(pset, buf);
|
||||
result = PSQLexec(buf);
|
||||
if (!result)
|
||||
error = true;
|
||||
else
|
||||
@ -710,7 +710,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
"WHERE i.indexrelid = c.oid AND c.relname = '%s' AND c.relam = a.oid",
|
||||
name);
|
||||
|
||||
result = PSQLexec(pset, buf);
|
||||
result = PSQLexec(buf);
|
||||
if (!result)
|
||||
error = true;
|
||||
else
|
||||
@ -750,7 +750,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
"WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
|
||||
"ORDER BY c2.relname",
|
||||
name);
|
||||
result1 = PSQLexec(pset, buf);
|
||||
result1 = PSQLexec(buf);
|
||||
if (!result1)
|
||||
error = true;
|
||||
else
|
||||
@ -764,7 +764,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
"FROM pg_relcheck r, pg_class c\n"
|
||||
"WHERE c.relname='%s' AND c.oid = r.rcrelid",
|
||||
name);
|
||||
result2 = PSQLexec(pset, buf);
|
||||
result2 = PSQLexec(buf);
|
||||
if (!result2)
|
||||
error = true;
|
||||
else
|
||||
@ -779,7 +779,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
"FROM pg_rewrite r, pg_class c\n"
|
||||
"WHERE c.relname='%s' AND c.oid = r.ev_class",
|
||||
name);
|
||||
result3 = PSQLexec(pset, buf);
|
||||
result3 = PSQLexec(buf);
|
||||
if (!result3)
|
||||
error = true;
|
||||
else
|
||||
@ -794,7 +794,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
"FROM pg_trigger t, pg_class c\n"
|
||||
"WHERE c.relname='%s' AND c.oid = t.tgrelid",
|
||||
name);
|
||||
result4 = PSQLexec(pset, buf);
|
||||
result4 = PSQLexec(buf);
|
||||
if (!result4)
|
||||
error = true;
|
||||
else
|
||||
@ -863,7 +863,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
|
||||
if (!error) {
|
||||
myopt.tuples_only = false;
|
||||
printTable(title, headers, (const char**)cells, (const char**)footers, "llll", &myopt, pset->queryFout);
|
||||
printTable(title, headers, (const char**)cells, (const char**)footers, "llll", &myopt, pset.queryFout);
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
@ -906,7 +906,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
|
||||
* tries to fix this the painful way, hopefully outer joins will be done sometime.
|
||||
*/
|
||||
bool
|
||||
listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc)
|
||||
listTables(const char *infotype, const char *name, bool desc)
|
||||
{
|
||||
bool showTables = strchr(infotype, 't') != NULL;
|
||||
bool showIndices = strchr(infotype, 'i') != NULL;
|
||||
@ -916,7 +916,7 @@ listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc
|
||||
|
||||
char buf[3072 + 8 * REGEXP_CUTOFF];
|
||||
PGresult *res;
|
||||
printQueryOpt myopt = pset->popt;
|
||||
printQueryOpt myopt = pset.popt;
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
@ -1093,20 +1093,24 @@ listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc
|
||||
strcat(buf, "\nORDER BY \"Name\"");
|
||||
|
||||
|
||||
res = PSQLexec(pset, buf);
|
||||
res = PSQLexec(buf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
if (PQntuples(res) == 0)
|
||||
fprintf(pset->queryFout, "No matching relations found.\n");
|
||||
|
||||
if (PQntuples(res) == 0 && !QUIET())
|
||||
{
|
||||
if (name)
|
||||
fprintf(pset.queryFout, "No matching relations found.\n");
|
||||
else
|
||||
fprintf(pset.queryFout, "No relations found.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
myopt.topt.tuples_only = false;
|
||||
myopt.nullPrint = NULL;
|
||||
myopt.title = "List of relations";
|
||||
|
||||
printQuery(res, &myopt, pset->queryFout);
|
||||
printQuery(res, &myopt, pset.queryFout);
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
@ -5,30 +5,30 @@
|
||||
#include "settings.h"
|
||||
|
||||
/* \da */
|
||||
bool describeAggregates(const char *name, PsqlSettings *pset);
|
||||
bool describeAggregates(const char *name);
|
||||
|
||||
/* \df */
|
||||
bool describeFunctions(const char *name, PsqlSettings *pset, bool verbose);
|
||||
bool describeFunctions(const char *name, bool verbose);
|
||||
|
||||
/* \dT */
|
||||
bool describeTypes(const char *name, PsqlSettings *pset, bool verbose);
|
||||
bool describeTypes(const char *name, bool verbose);
|
||||
|
||||
/* \do */
|
||||
bool describeOperators(const char *name, PsqlSettings *pset);
|
||||
bool describeOperators(const char *name);
|
||||
|
||||
/* \z (or \dp) */
|
||||
bool permissionsList(const char *name, PsqlSettings *pset);
|
||||
bool permissionsList(const char *name);
|
||||
|
||||
/* \dd */
|
||||
bool objectDescription(const char *object, PsqlSettings *pset);
|
||||
bool objectDescription(const char *object);
|
||||
|
||||
/* \d foo */
|
||||
bool describeTableDetails(const char *name, PsqlSettings *pset, bool desc);
|
||||
bool describeTableDetails(const char *name, bool desc);
|
||||
|
||||
/* \l */
|
||||
bool listAllDbs(PsqlSettings *pset, bool desc);
|
||||
bool listAllDbs(bool desc);
|
||||
|
||||
/* \dt, \di, \ds, \dS, etc. */
|
||||
bool listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc);
|
||||
bool listTables(const char *infotype, const char *name, bool desc);
|
||||
|
||||
#endif /* DESCRIBE_H */
|
||||
|
@ -149,7 +149,7 @@ struct winsize
|
||||
#endif
|
||||
|
||||
void
|
||||
slashUsage(PsqlSettings *pset)
|
||||
slashUsage(void)
|
||||
{
|
||||
bool usePipe = false;
|
||||
const char *pagerenv;
|
||||
@ -157,7 +157,7 @@ slashUsage(PsqlSettings *pset)
|
||||
struct winsize screen_size;
|
||||
|
||||
#ifdef TIOCGWINSZ
|
||||
if (pset->notty == 0 &&
|
||||
if (pset.notty == 0 &&
|
||||
(ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
|
||||
screen_size.ws_col == 0 ||
|
||||
screen_size.ws_row == 0))
|
||||
@ -169,7 +169,7 @@ slashUsage(PsqlSettings *pset)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pset->notty == 0 &&
|
||||
if (pset.notty == 0 &&
|
||||
(pagerenv = getenv("PAGER")) &&
|
||||
(pagerenv[0] != '\0') &&
|
||||
screen_size.ws_row <= 36 &&
|
||||
@ -184,7 +184,7 @@ slashUsage(PsqlSettings *pset)
|
||||
/* if you add/remove a line here, change the row test above */
|
||||
fprintf(fout, " \\? help\n");
|
||||
fprintf(fout, " \\c[onnect] [dbname|- [user|?]]\n"
|
||||
" connect to new database (currently '%s')\n", PQdb(pset->db));
|
||||
" 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, " \\copyright show PostgreSQL usage and distribution terms\n");
|
||||
fprintf(fout, " \\d <table> describe table (or view, index, sequence)\n");
|
||||
@ -209,9 +209,10 @@ slashUsage(PsqlSettings *pset)
|
||||
fprintf(fout, " \\qecho <text> write text to query output stream (see \\o)\n");
|
||||
fprintf(fout, " \\r reset (clear) the query buffer\n");
|
||||
fprintf(fout, " \\s [fname] print history or save it in <fname>\n");
|
||||
fprintf(fout, " \\set <var> [value] set/unset internal variable\n");
|
||||
fprintf(fout, " \\t don't show table headers or footers (currently %s)\n", ON(pset->popt.topt.tuples_only));
|
||||
fprintf(fout, " \\x toggle expanded output (currently %s)\n", ON(pset->popt.topt.expanded));
|
||||
fprintf(fout, " \\set <var> <value> set internal variable\n");
|
||||
fprintf(fout, " \\t don't show table headers or footers (currently %s)\n", ON(pset.popt.topt.tuples_only));
|
||||
fprintf(fout, " \\unset <var> unset (delete) internal variable\n");
|
||||
fprintf(fout, " \\x toggle expanded output (currently %s)\n", ON(pset.popt.topt.expanded));
|
||||
fprintf(fout, " \\w <fname> write current query buffer to a file\n");
|
||||
fprintf(fout, " \\z list table access permissions\n");
|
||||
fprintf(fout, " \\! [cmd] shell escape or command\n");
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
void usage(void);
|
||||
|
||||
void slashUsage(PsqlSettings *pset);
|
||||
void slashUsage(void);
|
||||
|
||||
void helpSQL(const char *topic);
|
||||
|
||||
|
@ -29,6 +29,10 @@ char *
|
||||
gets_interactive(const char *prompt)
|
||||
{
|
||||
char *s;
|
||||
#ifdef USE_HISTORY
|
||||
const char *var;
|
||||
static char * prev_hist = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef USE_READLINE
|
||||
if (useReadline)
|
||||
@ -45,7 +49,18 @@ gets_interactive(const char *prompt)
|
||||
|
||||
#ifdef USE_HISTORY
|
||||
if (useHistory && s && s[0] != '\0')
|
||||
{
|
||||
var = GetVariable(pset.vars, "HISTCONTROL");
|
||||
if (!var || (var
|
||||
&& !((strcmp(var, "ignorespace") == 0 || strcmp(var, "ignoreboth") ==0) && s[0] == ' ' )
|
||||
&& !((strcmp(var, "ignoredups") == 0 || strcmp(var, "ignoreboth") ==0) && prev_hist && strcmp(s, prev_hist) == 0)
|
||||
))
|
||||
{
|
||||
free(prev_hist);
|
||||
prev_hist = strdup(s);
|
||||
add_history(s);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return s;
|
||||
@ -93,14 +108,14 @@ gets_fromFile(FILE *source)
|
||||
* The only "flag" right now is 1 for use readline & history.
|
||||
*/
|
||||
void
|
||||
initializeInput(int flags, PsqlSettings *pset)
|
||||
initializeInput(int flags)
|
||||
{
|
||||
#ifdef USE_READLINE
|
||||
if (flags == 1)
|
||||
{
|
||||
useReadline = true;
|
||||
rl_readline_name = "psql";
|
||||
initialize_readline(&(pset->db));
|
||||
initialize_readline(&(pset.db));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -110,6 +125,7 @@ initializeInput(int flags, PsqlSettings *pset)
|
||||
const char *home;
|
||||
|
||||
useHistory = true;
|
||||
SetVariable(pset.vars, "HISTSIZE", "500");
|
||||
using_history();
|
||||
home = getenv("HOME");
|
||||
if (home)
|
||||
@ -166,6 +182,9 @@ finishInput(void)
|
||||
psql_history = (char *) malloc(strlen(home) + 20);
|
||||
if (psql_history)
|
||||
{
|
||||
const char * var = GetVariable(pset.vars, "HISTSIZE");
|
||||
if (var)
|
||||
stifle_history(atoi(var));
|
||||
sprintf(psql_history, "%s/.psql_history", home);
|
||||
write_history(psql_history);
|
||||
free(psql_history);
|
||||
|
@ -42,7 +42,7 @@ char * gets_interactive(const char *prompt);
|
||||
char * gets_fromFile(FILE *source);
|
||||
|
||||
|
||||
void initializeInput(int flags, PsqlSettings *pset);
|
||||
void initializeInput(int flags);
|
||||
|
||||
bool saveHistory(const char *fname);
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <config.h>
|
||||
#include <c.h>
|
||||
#include "large_obj.h"
|
||||
|
||||
@ -33,9 +32,9 @@ _my_notice_handler(void *arg, const char *message)
|
||||
|
||||
|
||||
static bool
|
||||
handle_transaction(PsqlSettings *pset)
|
||||
handle_transaction(void)
|
||||
{
|
||||
const char *var = GetVariable(pset->vars, "lo_transaction");
|
||||
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
|
||||
PGresult *res;
|
||||
bool commit;
|
||||
PQnoticeProcessor old_notice_hook;
|
||||
@ -46,9 +45,9 @@ handle_transaction(PsqlSettings *pset)
|
||||
commit = (var && strcmp(var, "commit") == 0);
|
||||
|
||||
notice[0] = '\0';
|
||||
old_notice_hook = PQsetNoticeProcessor(pset->db, _my_notice_handler, NULL);
|
||||
old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL);
|
||||
|
||||
res = PSQLexec(pset, commit ? "COMMIT" : "ROLLBACK");
|
||||
res = PSQLexec(commit ? "COMMIT" : "ROLLBACK");
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
@ -58,7 +57,7 @@ handle_transaction(PsqlSettings *pset)
|
||||
(commit && strcmp(notice, "NOTICE: EndTransactionBlock and not inprogress/abort state\n") != 0))
|
||||
fputs(notice, stderr);
|
||||
}
|
||||
else if (!GetVariableBool(pset->vars, "quiet"))
|
||||
else if (!QUIET())
|
||||
{
|
||||
if (commit)
|
||||
puts("Warning: Your transaction in progress has been committed.");
|
||||
@ -66,7 +65,7 @@ handle_transaction(PsqlSettings *pset)
|
||||
puts("Warning: Your transaction in progress has been rolled back.");
|
||||
}
|
||||
|
||||
PQsetNoticeProcessor(pset->db, old_notice_hook, NULL);
|
||||
PQsetNoticeProcessor(pset.db, old_notice_hook, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -78,43 +77,43 @@ handle_transaction(PsqlSettings *pset)
|
||||
* Write a large object to a file
|
||||
*/
|
||||
bool
|
||||
do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
|
||||
do_lo_export(const char *loid_arg, const char *filename_arg)
|
||||
{
|
||||
PGresult *res;
|
||||
int status;
|
||||
bool own_transaction = true;
|
||||
const char *var = GetVariable(pset->vars, "lo_transaction");
|
||||
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
|
||||
|
||||
if (var && strcmp(var, "nothing") == 0)
|
||||
own_transaction = false;
|
||||
|
||||
if (!pset->db)
|
||||
if (!pset.db)
|
||||
{
|
||||
if (!pset->cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset->progname);
|
||||
if (!pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset.progname);
|
||||
fputs("\\lo_export: not connected to a database\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!handle_transaction(pset))
|
||||
if (!handle_transaction())
|
||||
return false;
|
||||
|
||||
if (!(res = PSQLexec(pset, "BEGIN")))
|
||||
if (!(res = PSQLexec("BEGIN")))
|
||||
return false;
|
||||
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
status = lo_export(pset->db, atol(loid_arg), (char *) filename_arg);
|
||||
status = lo_export(pset.db, atol(loid_arg), (char *) filename_arg);
|
||||
if (status != 1)
|
||||
{ /* of course this status is documented
|
||||
* nowhere :( */
|
||||
fputs(PQerrorMessage(pset->db), stderr);
|
||||
fputs(PQerrorMessage(pset.db), stderr);
|
||||
if (own_transaction)
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
res = PQexec(pset.db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
}
|
||||
return false;
|
||||
@ -122,9 +121,9 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
|
||||
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!(res = PSQLexec(pset, "COMMIT")))
|
||||
if (!(res = PSQLexec("COMMIT")))
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
res = PQexec(pset.db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
return false;
|
||||
}
|
||||
@ -132,7 +131,7 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
fprintf(pset->queryFout, "lo_export\n");
|
||||
fprintf(pset.queryFout, "lo_export\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -145,44 +144,44 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
|
||||
* Copy large object from file to database
|
||||
*/
|
||||
bool
|
||||
do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_arg)
|
||||
do_lo_import(const char *filename_arg, const char *comment_arg)
|
||||
{
|
||||
PGresult *res;
|
||||
Oid loid;
|
||||
char buf[1024];
|
||||
unsigned int i;
|
||||
bool own_transaction = true;
|
||||
const char *var = GetVariable(pset->vars, "lo_transaction");
|
||||
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
|
||||
|
||||
if (var && strcmp(var, "nothing") == 0)
|
||||
own_transaction = false;
|
||||
|
||||
if (!pset->db)
|
||||
if (!pset.db)
|
||||
{
|
||||
if (!pset->cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset->progname);
|
||||
if (!pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset.progname);
|
||||
fputs("\\lo_import: not connected to a database\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!handle_transaction(pset))
|
||||
if (!handle_transaction())
|
||||
return false;
|
||||
|
||||
if (!(res = PSQLexec(pset, "BEGIN")))
|
||||
if (!(res = PSQLexec("BEGIN")))
|
||||
return false;
|
||||
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
loid = lo_import(pset->db, (char *) filename_arg);
|
||||
loid = lo_import(pset.db, (char *) filename_arg);
|
||||
if (loid == InvalidOid)
|
||||
{
|
||||
fputs(PQerrorMessage(pset->db), stderr);
|
||||
fputs(PQerrorMessage(pset.db), stderr);
|
||||
if (own_transaction)
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
res = PQexec(pset.db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
}
|
||||
return false;
|
||||
@ -199,11 +198,11 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
|
||||
strncat(buf, &comment_arg[i], 1);
|
||||
strcat(buf, "')");
|
||||
|
||||
if (!(res = PSQLexec(pset, buf)))
|
||||
if (!(res = PSQLexec(buf)))
|
||||
{
|
||||
if (own_transaction)
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
res = PQexec(pset.db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
}
|
||||
return false;
|
||||
@ -212,9 +211,9 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
|
||||
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!(res = PSQLexec(pset, "COMMIT")))
|
||||
if (!(res = PSQLexec("COMMIT")))
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
res = PQexec(pset.db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
return false;
|
||||
}
|
||||
@ -223,8 +222,9 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
|
||||
}
|
||||
|
||||
|
||||
fprintf(pset->queryFout, "lo_import %d\n", loid);
|
||||
pset->lastOid = loid;
|
||||
fprintf(pset.queryFout, "lo_import %d\n", loid);
|
||||
sprintf(buf, "%u", (unsigned int)loid);
|
||||
SetVariable(pset.vars, "LASTOID", buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -237,44 +237,44 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
|
||||
* removes a large object out of the database
|
||||
*/
|
||||
bool
|
||||
do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
|
||||
do_lo_unlink(const char *loid_arg)
|
||||
{
|
||||
PGresult *res;
|
||||
int status;
|
||||
Oid loid = (Oid) atol(loid_arg);
|
||||
char buf[256];
|
||||
bool own_transaction = true;
|
||||
const char *var = GetVariable(pset->vars, "lo_transaction");
|
||||
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
|
||||
|
||||
if (var && strcmp(var, "nothing") == 0)
|
||||
own_transaction = false;
|
||||
|
||||
if (!pset->db)
|
||||
if (!pset.db)
|
||||
{
|
||||
if (!pset->cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset->progname);
|
||||
if (!pset.cur_cmd_interactive)
|
||||
fprintf(stderr, "%s: ", pset.progname);
|
||||
fputs("\\lo_unlink: not connected to a database\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!handle_transaction(pset))
|
||||
if (!handle_transaction())
|
||||
return false;
|
||||
|
||||
if (!(res = PSQLexec(pset, "BEGIN")))
|
||||
if (!(res = PSQLexec("BEGIN")))
|
||||
return false;
|
||||
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
status = lo_unlink(pset->db, loid);
|
||||
status = lo_unlink(pset.db, loid);
|
||||
if (status == -1)
|
||||
{
|
||||
fputs(PQerrorMessage(pset->db), stderr);
|
||||
fputs(PQerrorMessage(pset.db), stderr);
|
||||
if (own_transaction)
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
res = PQexec(pset.db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
}
|
||||
return false;
|
||||
@ -282,11 +282,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
|
||||
|
||||
/* remove the comment as well */
|
||||
sprintf(buf, "DELETE FROM pg_description WHERE objoid = %d", loid);
|
||||
if (!(res = PSQLexec(pset, buf)))
|
||||
if (!(res = PSQLexec(buf)))
|
||||
{
|
||||
if (own_transaction)
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
res = PQexec(pset.db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
}
|
||||
return false;
|
||||
@ -295,9 +295,9 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
|
||||
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!(res = PSQLexec(pset, "COMMIT")))
|
||||
if (!(res = PSQLexec("COMMIT")))
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
res = PQexec(pset.db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
return false;
|
||||
}
|
||||
@ -305,7 +305,7 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
|
||||
}
|
||||
|
||||
|
||||
fprintf(pset->queryFout, "lo_unlink %d\n", loid);
|
||||
fprintf(pset.queryFout, "lo_unlink %d\n", loid);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -318,11 +318,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
|
||||
* Show all large objects in database with comments
|
||||
*/
|
||||
bool
|
||||
do_lo_list(PsqlSettings *pset)
|
||||
do_lo_list(void)
|
||||
{
|
||||
PGresult *res;
|
||||
char buf[1024];
|
||||
printQueryOpt myopt = pset->popt;
|
||||
printQueryOpt myopt = pset.popt;
|
||||
|
||||
strcpy(buf,
|
||||
"SELECT usename as \"Owner\", substring(relname from 5) as \"ID\",\n"
|
||||
@ -336,7 +336,7 @@ do_lo_list(PsqlSettings *pset)
|
||||
"WHERE not exists (select 1 from pg_user where usesysid = relowner) AND relkind = 'l'\n"
|
||||
"ORDER BY \"ID\"");
|
||||
|
||||
res = PSQLexec(pset, buf);
|
||||
res = PSQLexec(buf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
@ -344,7 +344,7 @@ do_lo_list(PsqlSettings *pset)
|
||||
myopt.nullPrint = NULL;
|
||||
myopt.title = "Large objects";
|
||||
|
||||
printQuery(res, &myopt, pset->queryFout);
|
||||
printQuery(res, &myopt, pset.queryFout);
|
||||
|
||||
PQclear(res);
|
||||
return true;
|
||||
|
@ -2,11 +2,10 @@
|
||||
#define LARGE_OBJ_H
|
||||
|
||||
#include <c.h>
|
||||
#include "settings.h"
|
||||
|
||||
bool do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg);
|
||||
bool do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_arg);
|
||||
bool do_lo_unlink(PsqlSettings *pset, const char *loid_arg);
|
||||
bool do_lo_list(PsqlSettings *pset);
|
||||
bool do_lo_export(const char *loid_arg, const char *filename_arg);
|
||||
bool do_lo_import(const char *filename_arg, const char *comment_arg);
|
||||
bool do_lo_unlink(const char *loid_arg);
|
||||
bool do_lo_list(void);
|
||||
|
||||
#endif /* LARGE_OBJ_H */
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <config.h>
|
||||
#include <c.h>
|
||||
#include "mainloop.h"
|
||||
|
||||
@ -26,7 +25,7 @@
|
||||
* FIXME: rewrite this whole thing with flex
|
||||
*/
|
||||
int
|
||||
MainLoop(PsqlSettings *pset, FILE *source)
|
||||
MainLoop(FILE *source)
|
||||
{
|
||||
PQExpBuffer query_buf; /* buffer for query being accumulated */
|
||||
PQExpBuffer previous_buf; /* if there isn't anything in the new buffer
|
||||
@ -36,13 +35,14 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
int successResult = EXIT_SUCCESS;
|
||||
backslashResult slashCmdStatus;
|
||||
|
||||
bool eof = false; /* end of our command input? */
|
||||
bool success;
|
||||
char in_quote; /* == 0 for no in_quote */
|
||||
bool was_bslash; /* backslash */
|
||||
bool xcomment; /* in extended comment */
|
||||
int paren_level;
|
||||
unsigned int query_start;
|
||||
int count_eof;
|
||||
const char *var;
|
||||
|
||||
int i,
|
||||
prevlen,
|
||||
@ -56,12 +56,12 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
|
||||
|
||||
/* Save old settings */
|
||||
prev_cmd_source = pset->cur_cmd_source;
|
||||
prev_cmd_interactive = pset->cur_cmd_interactive;
|
||||
prev_cmd_source = pset.cur_cmd_source;
|
||||
prev_cmd_interactive = pset.cur_cmd_interactive;
|
||||
|
||||
/* Establish new source */
|
||||
pset->cur_cmd_source = source;
|
||||
pset->cur_cmd_interactive = ((source == stdin) && !pset->notty);
|
||||
pset.cur_cmd_source = source;
|
||||
pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
|
||||
|
||||
|
||||
query_buf = createPQExpBuffer();
|
||||
@ -79,7 +79,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
|
||||
|
||||
/* main loop to get queries and execute them */
|
||||
while (!eof)
|
||||
while (1)
|
||||
{
|
||||
if (slashCmdStatus == CMD_NEWEDIT)
|
||||
{
|
||||
@ -102,7 +102,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
* otherwise, set interactive prompt if necessary and get
|
||||
* another line
|
||||
*/
|
||||
if (pset->cur_cmd_interactive)
|
||||
if (pset.cur_cmd_interactive)
|
||||
{
|
||||
int prompt_status;
|
||||
|
||||
@ -117,7 +117,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
else
|
||||
prompt_status = PROMPT_READY;
|
||||
|
||||
line = gets_interactive(get_prompt(pset, prompt_status));
|
||||
line = gets_interactive(get_prompt(prompt_status));
|
||||
}
|
||||
else
|
||||
line = gets_fromFile(source);
|
||||
@ -125,7 +125,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
|
||||
|
||||
/* Setting this will not have effect until next line. */
|
||||
die_on_error = GetVariableBool(pset->vars, "die_on_error");
|
||||
die_on_error = GetVariableBool(pset.vars, "EXIT_ON_ERROR");
|
||||
|
||||
/*
|
||||
* query_buf holds query already accumulated. line is the
|
||||
@ -137,14 +137,47 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
/* No more input. Time to quit, or \i done */
|
||||
if (line == NULL)
|
||||
{
|
||||
if (GetVariableBool(pset->vars, "echo") && !GetVariableBool(pset->vars, "quiet"))
|
||||
puts("EOF");
|
||||
else if (pset->cur_cmd_interactive)
|
||||
putc('\n', stdout); /* just newline */
|
||||
if (pset.cur_cmd_interactive)
|
||||
{
|
||||
bool getout = true;
|
||||
|
||||
eof = true;
|
||||
/* This tries to mimic bash's IGNOREEOF feature. */
|
||||
const char * val = GetVariable(pset.vars, "IGNOREEOF");
|
||||
if (val)
|
||||
{
|
||||
long int maxeof;
|
||||
char * endptr;
|
||||
|
||||
if (*val == '\0')
|
||||
maxeof = 10;
|
||||
else
|
||||
{
|
||||
maxeof = strtol(val, &endptr, 0);
|
||||
if (*endptr != '\0') /* string not valid as a number */
|
||||
maxeof = 10;
|
||||
}
|
||||
|
||||
if (count_eof++ != maxeof)
|
||||
getout = false; /* not quite there yet */
|
||||
}
|
||||
|
||||
if (getout)
|
||||
{
|
||||
putc('\n', stdout); /* just newline */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!QUIET())
|
||||
printf("Use \"\\q\" to leave %s.\n", pset.progname);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else /* not interactive */
|
||||
break;
|
||||
}
|
||||
else
|
||||
count_eof = 0;
|
||||
|
||||
/* strip trailing backslashes, they don't have a clear meaning */
|
||||
while (1)
|
||||
@ -164,11 +197,11 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* echo back if input is from file and flag is set */
|
||||
if (!pset->cur_cmd_interactive && GetVariableBool(pset->vars, "echo"))
|
||||
/* echo back if flag is set */
|
||||
var = GetVariable(pset.vars, "ECHO");
|
||||
if (var && strcmp(var, "full")==0)
|
||||
puts(line);
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
len = strlen(line);
|
||||
query_start = 0;
|
||||
@ -236,8 +269,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
/* colon -> substitute variable */
|
||||
/* we need to be on the watch for the '::' operator */
|
||||
else if (line[i] == ':' && !was_bslash &&
|
||||
strspn(line+i+thislen, VALID_VARIABLE_CHARS)>0 &&
|
||||
(prevlen > 0 && line[i-prevlen]!=':')
|
||||
strspn(line+i+thislen, VALID_VARIABLE_CHARS)>0
|
||||
)
|
||||
{
|
||||
size_t in_length,
|
||||
@ -250,7 +282,11 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
in_length = strspn(&line[i + thislen], VALID_VARIABLE_CHARS);
|
||||
after = line[i + thislen + in_length];
|
||||
line[i + thislen + in_length] = '\0';
|
||||
value = interpolate_var(&line[i + thislen], pset);
|
||||
|
||||
/* if the variable doesn't exist we'll leave the string as is */
|
||||
value = GetVariable(pset.vars, &line[i + thislen]);
|
||||
if (value)
|
||||
{
|
||||
out_length = strlen(value);
|
||||
|
||||
new = malloc(len + out_length - (1 + in_length) + 1);
|
||||
@ -269,6 +305,13 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
len = strlen(new);
|
||||
continue; /* reparse the just substituted */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* restore overwritten character */
|
||||
line[i + thislen + in_length] = after;
|
||||
/* move on ... */
|
||||
}
|
||||
}
|
||||
|
||||
/* semicolon? then send query */
|
||||
else if (line[i] == ';' && !was_bslash && !paren_level)
|
||||
@ -288,7 +331,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
}
|
||||
|
||||
/* execute query */
|
||||
success = SendQuery(pset, query_buf->data);
|
||||
success = SendQuery(query_buf->data);
|
||||
slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
|
||||
|
||||
resetPQExpBuffer(previous_buf);
|
||||
@ -314,7 +357,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
paren_level = 0;
|
||||
line[i - prevlen] = '\0'; /* overwrites backslash */
|
||||
|
||||
/* is there anything else on the line? */
|
||||
/* is there anything else on the line for the command? */
|
||||
if (line[query_start + strspn(line + query_start, " \t")] != '\0')
|
||||
{
|
||||
/*
|
||||
@ -328,7 +371,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
}
|
||||
|
||||
/* handle backslash command */
|
||||
slashCmdStatus = HandleSlashCmds(pset, &line[i],
|
||||
slashCmdStatus = HandleSlashCmds(&line[i],
|
||||
query_buf->len>0 ? query_buf : previous_buf,
|
||||
&end_of_cmd);
|
||||
|
||||
@ -342,7 +385,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
|
||||
if (slashCmdStatus == CMD_SEND)
|
||||
{
|
||||
success = SendQuery(pset, query_buf->data);
|
||||
success = SendQuery(query_buf->data);
|
||||
query_start = i + thislen;
|
||||
|
||||
resetPQExpBuffer(previous_buf);
|
||||
@ -350,15 +393,10 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
resetPQExpBuffer(query_buf);
|
||||
}
|
||||
|
||||
/* is there anything left after the backslash command? */
|
||||
if (end_of_cmd)
|
||||
{
|
||||
/* process anything left after the backslash command */
|
||||
i += end_of_cmd - &line[i];
|
||||
query_start = i;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* stop the script after error */
|
||||
@ -387,9 +425,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
|
||||
|
||||
/* In single line mode, send off the query if any */
|
||||
if (query_buf->data[0] != '\0' && GetVariableBool(pset->vars, "singleline"))
|
||||
if (query_buf->data[0] != '\0' && GetVariableBool(pset.vars, "SINGLELINE"))
|
||||
{
|
||||
success = SendQuery(pset, query_buf->data);
|
||||
success = SendQuery(query_buf->data);
|
||||
slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
|
||||
resetPQExpBuffer(previous_buf);
|
||||
appendPQExpBufferStr(previous_buf, query_buf->data);
|
||||
@ -397,7 +435,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
}
|
||||
|
||||
|
||||
if (!success && die_on_error && !pset->cur_cmd_interactive)
|
||||
if (!success && die_on_error && !pset.cur_cmd_interactive)
|
||||
{
|
||||
successResult = EXIT_USER;
|
||||
break;
|
||||
@ -405,18 +443,18 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
|
||||
|
||||
/* Have we lost the db connection? */
|
||||
if (pset->db == NULL && !pset->cur_cmd_interactive)
|
||||
if (pset.db == NULL && !pset.cur_cmd_interactive)
|
||||
{
|
||||
successResult = EXIT_BADCONN;
|
||||
break;
|
||||
}
|
||||
} /* while !EOF */
|
||||
} /* while !endofprogram */
|
||||
|
||||
destroyPQExpBuffer(query_buf);
|
||||
destroyPQExpBuffer(previous_buf);
|
||||
|
||||
pset->cur_cmd_source = prev_cmd_source;
|
||||
pset->cur_cmd_interactive = prev_cmd_interactive;
|
||||
pset.cur_cmd_source = prev_cmd_source;
|
||||
pset.cur_cmd_interactive = prev_cmd_interactive;
|
||||
|
||||
return successResult;
|
||||
} /* MainLoop() */
|
||||
|
@ -2,9 +2,7 @@
|
||||
#define MAINLOOP_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "settings.h"
|
||||
|
||||
int
|
||||
MainLoop(PsqlSettings *pset, FILE *source);
|
||||
int MainLoop(FILE *source);
|
||||
|
||||
#endif /* MAINLOOP_H */
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <config.h>
|
||||
#include <c.h>
|
||||
#include "prompt.h"
|
||||
|
||||
@ -10,6 +9,7 @@
|
||||
|
||||
#include "settings.h"
|
||||
#include "common.h"
|
||||
#include "variables.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define popen(x,y) _popen(x,y)
|
||||
@ -22,7 +22,7 @@
|
||||
* get_prompt
|
||||
*
|
||||
* Returns a statically allocated prompt made by interpolating certain
|
||||
* tcsh style escape sequences into pset->vars "prompt1|2|3".
|
||||
* tcsh style escape sequences into pset->vars "PROMPT1|2|3".
|
||||
* (might not be completely multibyte safe)
|
||||
*
|
||||
* Defined interpolations are:
|
||||
@ -46,8 +46,7 @@
|
||||
*
|
||||
* %`command` - The result of executing command in /bin/sh with trailing
|
||||
* newline stripped.
|
||||
* %$name$ - The value of the psql/environment/magic varible 'name'
|
||||
* (same rules as for, e.g., \echo $foo)
|
||||
* %$name$ - The value of the psql variable 'name'
|
||||
* (those will not be rescanned for more escape sequences!)
|
||||
*
|
||||
*
|
||||
@ -56,7 +55,7 @@
|
||||
*--------------------------
|
||||
*/
|
||||
const char *
|
||||
get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
get_prompt(promptStatus_t status)
|
||||
{
|
||||
#define MAX_PROMPT_SIZE 256
|
||||
static char destination[MAX_PROMPT_SIZE + 1];
|
||||
@ -66,11 +65,11 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
const char *prompt_string;
|
||||
|
||||
if (status == PROMPT_READY)
|
||||
prompt_string = GetVariable(pset->vars, "prompt1");
|
||||
prompt_string = GetVariable(pset.vars, "PROMPT1");
|
||||
else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status == PROMPT_COMMENT)
|
||||
prompt_string = GetVariable(pset->vars, "prompt2");
|
||||
prompt_string = GetVariable(pset.vars, "PROMPT2");
|
||||
else if (status == PROMPT_COPY)
|
||||
prompt_string = GetVariable(pset->vars, "prompt3");
|
||||
prompt_string = GetVariable(pset.vars, "PROMPT3");
|
||||
else
|
||||
prompt_string = "? ";
|
||||
|
||||
@ -92,31 +91,31 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
|
||||
/* Current database */
|
||||
case '/':
|
||||
if (pset->db)
|
||||
strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
|
||||
if (pset.db)
|
||||
strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
|
||||
break;
|
||||
case '~':
|
||||
{
|
||||
const char *var;
|
||||
|
||||
if (pset->db)
|
||||
if (pset.db)
|
||||
{
|
||||
if (strcmp(PQdb(pset->db), PQuser(pset->db)) == 0 ||
|
||||
((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset->db)) == 0))
|
||||
if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
|
||||
((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
|
||||
strcpy(buf, "~");
|
||||
else
|
||||
strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
|
||||
strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* DB server hostname (long/short) */
|
||||
case 'M':
|
||||
case 'm':
|
||||
if (pset->db)
|
||||
if (pset.db)
|
||||
{
|
||||
if (PQhost(pset->db))
|
||||
if (PQhost(pset.db))
|
||||
{
|
||||
strncpy(buf, PQhost(pset->db), MAX_PROMPT_SIZE);
|
||||
strncpy(buf, PQhost(pset.db), MAX_PROMPT_SIZE);
|
||||
if (*p == 'm')
|
||||
buf[strcspn(buf, ".")] = '\0';
|
||||
}
|
||||
@ -126,13 +125,13 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
break;
|
||||
/* DB server port number */
|
||||
case '>':
|
||||
if (pset->db && PQport(pset->db))
|
||||
strncpy(buf, PQport(pset->db), MAX_PROMPT_SIZE);
|
||||
if (pset.db && PQport(pset.db))
|
||||
strncpy(buf, PQport(pset.db), MAX_PROMPT_SIZE);
|
||||
break;
|
||||
/* DB server user name */
|
||||
case 'n':
|
||||
if (pset->db)
|
||||
strncpy(buf, PQuser(pset->db), MAX_PROMPT_SIZE);
|
||||
if (pset.db)
|
||||
strncpy(buf, PQuser(pset.db), MAX_PROMPT_SIZE);
|
||||
break;
|
||||
|
||||
case '0':
|
||||
@ -159,9 +158,9 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
switch (status)
|
||||
{
|
||||
case PROMPT_READY:
|
||||
if (!pset->db)
|
||||
if (!pset.db)
|
||||
buf[0] = '!';
|
||||
else if (!GetVariableBool(pset->vars, "singleline"))
|
||||
else if (!GetVariableBool(pset.vars, "SINGLELINE"))
|
||||
buf[0] = '=';
|
||||
else
|
||||
buf[0] = '^';
|
||||
@ -189,7 +188,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
|
||||
case '#':
|
||||
{
|
||||
if (pset->db && strcmp(PQuser(pset->db), "postgres") == 0)
|
||||
if (pset.db && strcmp(PQuser(pset.db), "postgres") == 0)
|
||||
buf[0] = '#';
|
||||
else
|
||||
buf[0] = '>';
|
||||
@ -230,7 +229,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
name = strdup(p + 1);
|
||||
nameend = strcspn(name, "$");
|
||||
name[nameend] = '\0';
|
||||
val = interpolate_var(name, pset);
|
||||
val = GetVariable(pset.vars, name);
|
||||
if (val)
|
||||
strncpy(buf, val, MAX_PROMPT_SIZE);
|
||||
free(name);
|
||||
|
@ -14,7 +14,7 @@ typedef enum _promptStatus
|
||||
} promptStatus_t;
|
||||
|
||||
const char *
|
||||
get_prompt(PsqlSettings *pset, promptStatus_t status);
|
||||
get_prompt(promptStatus_t status);
|
||||
|
||||
|
||||
#endif /* PROMPT_H */
|
||||
|
@ -43,11 +43,13 @@ typedef struct _psqlSettings
|
||||
|
||||
bool has_client_encoding; /* was PGCLIENTENCODING set on
|
||||
* startup? */
|
||||
Oid lastOid; /* saves oid from insert command
|
||||
because people want it so badly */
|
||||
char *progname; /* in case you renamed psql */
|
||||
} PsqlSettings;
|
||||
|
||||
extern PsqlSettings pset;
|
||||
|
||||
|
||||
#define QUIET() (GetVariableBool(pset.vars, "QUIET"))
|
||||
|
||||
|
||||
#ifndef EXIT_SUCCESS
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <config.h>
|
||||
#include <c.h>
|
||||
|
||||
#include <signal.h>
|
||||
@ -34,10 +33,10 @@
|
||||
#include "print.h"
|
||||
#include "describe.h"
|
||||
|
||||
|
||||
PsqlSettings pset;
|
||||
|
||||
static void
|
||||
process_psqlrc(PsqlSettings *pset);
|
||||
process_psqlrc(void);
|
||||
|
||||
static void
|
||||
showVersion(void);
|
||||
@ -67,7 +66,7 @@ struct adhoc_opts
|
||||
};
|
||||
|
||||
static void
|
||||
parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * options);
|
||||
parse_options(int argc, char *argv[], struct adhoc_opts * options);
|
||||
|
||||
|
||||
|
||||
@ -79,7 +78,6 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
PsqlSettings settings;
|
||||
struct adhoc_opts options;
|
||||
int successResult;
|
||||
|
||||
@ -87,64 +85,65 @@ main(int argc, char **argv)
|
||||
char *password = NULL;
|
||||
bool need_pass;
|
||||
|
||||
memset(&settings, 0, sizeof settings);
|
||||
memset(&pset, 0, sizeof pset);
|
||||
|
||||
if (!strrchr(argv[0], SEP_CHAR))
|
||||
settings.progname = argv[0];
|
||||
pset.progname = argv[0];
|
||||
else
|
||||
settings.progname = strrchr(argv[0], SEP_CHAR) + 1;
|
||||
pset.progname = strrchr(argv[0], SEP_CHAR) + 1;
|
||||
|
||||
settings.cur_cmd_source = stdin;
|
||||
settings.cur_cmd_interactive = false;
|
||||
pset.cur_cmd_source = stdin;
|
||||
pset.cur_cmd_interactive = false;
|
||||
|
||||
settings.vars = CreateVariableSpace();
|
||||
settings.popt.topt.format = PRINT_ALIGNED;
|
||||
settings.queryFout = stdout;
|
||||
settings.popt.topt.fieldSep = strdup(DEFAULT_FIELD_SEP);
|
||||
settings.popt.topt.border = 1;
|
||||
settings.popt.topt.pager = 1;
|
||||
pset.vars = CreateVariableSpace();
|
||||
pset.popt.topt.format = PRINT_ALIGNED;
|
||||
pset.queryFout = stdout;
|
||||
pset.popt.topt.fieldSep = strdup(DEFAULT_FIELD_SEP);
|
||||
pset.popt.topt.border = 1;
|
||||
pset.popt.topt.pager = 1;
|
||||
|
||||
SetVariable(settings.vars, "prompt1", DEFAULT_PROMPT1);
|
||||
SetVariable(settings.vars, "prompt2", DEFAULT_PROMPT2);
|
||||
SetVariable(settings.vars, "prompt3", DEFAULT_PROMPT3);
|
||||
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);
|
||||
|
||||
settings.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
|
||||
pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
|
||||
|
||||
/* This is obsolete and will be removed very soon. */
|
||||
#ifdef PSQL_ALWAYS_GET_PASSWORDS
|
||||
settings.getPassword = true;
|
||||
pset.getPassword = true;
|
||||
#else
|
||||
settings.getPassword = false;
|
||||
pset.getPassword = false;
|
||||
#endif
|
||||
|
||||
#ifdef MULTIBYTE
|
||||
settings.has_client_encoding = (getenv("PGCLIENTENCODING") != NULL);
|
||||
pset.has_client_encoding = (getenv("PGCLIENTENCODING") != NULL);
|
||||
#endif
|
||||
|
||||
parse_options(argc, argv, &settings, &options);
|
||||
parse_options(argc, argv, &options);
|
||||
|
||||
if (options.action == ACT_LIST_DB)
|
||||
options.dbname = "template1";
|
||||
|
||||
if (options.username)
|
||||
{
|
||||
if (strcmp(options.username, "?") == 0)
|
||||
if (strcmp(options.username, "\001") == 0)
|
||||
username = simple_prompt("Username: ", 100, true);
|
||||
else
|
||||
username = strdup(options.username);
|
||||
}
|
||||
|
||||
if (settings.getPassword)
|
||||
if (pset.getPassword)
|
||||
password = simple_prompt("Password: ", 100, false);
|
||||
|
||||
/* loop until we have a password if requested by backend */
|
||||
do
|
||||
{
|
||||
need_pass = false;
|
||||
settings.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.dbname, username, password);
|
||||
pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.dbname, username, password);
|
||||
|
||||
if (PQstatus(settings.db) == CONNECTION_BAD &&
|
||||
strcmp(PQerrorMessage(settings.db), "fe_sendauth: no password supplied\n") == 0)
|
||||
if (PQstatus(pset.db) == CONNECTION_BAD &&
|
||||
strcmp(PQerrorMessage(pset.db), "fe_sendauth: no password supplied\n") == 0)
|
||||
{
|
||||
need_pass = true;
|
||||
free(password);
|
||||
@ -156,58 +155,61 @@ main(int argc, char **argv)
|
||||
free(username);
|
||||
free(password);
|
||||
|
||||
if (PQstatus(settings.db) == CONNECTION_BAD)
|
||||
if (PQstatus(pset.db) == CONNECTION_BAD)
|
||||
{
|
||||
fprintf(stderr, "%s: connection to database '%s' failed.\n%s",
|
||||
settings.progname, PQdb(settings.db),
|
||||
PQerrorMessage(settings.db));
|
||||
PQfinish(settings.db);
|
||||
fprintf(stderr, "%s: connection to database '%s' failed - %s",
|
||||
pset.progname, PQdb(pset.db), PQerrorMessage(pset.db));
|
||||
PQfinish(pset.db);
|
||||
exit(EXIT_BADCONN);
|
||||
}
|
||||
|
||||
if (options.action == ACT_LIST_DB)
|
||||
{
|
||||
int success = listAllDbs(&settings, false);
|
||||
int success = listAllDbs(false);
|
||||
|
||||
PQfinish(settings.db);
|
||||
PQfinish(pset.db);
|
||||
exit(!success);
|
||||
}
|
||||
|
||||
SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
|
||||
SetVariable(pset.vars, "USER", PQuser(pset.db));
|
||||
SetVariable(pset.vars, "HOST", PQhost(pset.db));
|
||||
SetVariable(pset.vars, "PORT", PQport(pset.db));
|
||||
|
||||
if (!GetVariable(settings.vars, "quiet") && !settings.notty && !options.action)
|
||||
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", settings.progname);
|
||||
" \\q to quit\n", pset.progname);
|
||||
}
|
||||
|
||||
process_psqlrc(&settings);
|
||||
|
||||
initializeInput(options.no_readline ? 0 : 1, &settings);
|
||||
|
||||
/* Now find something to do */
|
||||
|
||||
/* process file given by -f */
|
||||
if (options.action == ACT_FILE)
|
||||
successResult = process_file(options.action_string, &settings) ? 0 : 1;
|
||||
successResult = process_file(options.action_string) ? 0 : 1;
|
||||
/* process slash command if one was given to -c */
|
||||
else if (options.action == ACT_SINGLE_SLASH)
|
||||
successResult = HandleSlashCmds(&settings, options.action_string, NULL, NULL) != CMD_ERROR ? 0 : 1;
|
||||
successResult = HandleSlashCmds(options.action_string, NULL, NULL) != CMD_ERROR ? 0 : 1;
|
||||
/* If the query given to -c was a normal one, send it */
|
||||
else if (options.action == ACT_SINGLE_QUERY)
|
||||
successResult = SendQuery(&settings, options.action_string) ? 0 : 1;
|
||||
successResult = SendQuery( options.action_string) ? 0 : 1;
|
||||
/* or otherwise enter interactive main loop */
|
||||
else
|
||||
successResult = MainLoop(&settings, stdin);
|
||||
{
|
||||
process_psqlrc();
|
||||
initializeInput(options.no_readline ? 0 : 1);
|
||||
successResult = MainLoop(stdin);
|
||||
finishInput();
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
finishInput();
|
||||
PQfinish(settings.db);
|
||||
setQFout(NULL, &settings);
|
||||
DestroyVariableSpace(settings.vars);
|
||||
PQfinish(pset.db);
|
||||
setQFout(NULL);
|
||||
DestroyVariableSpace(pset.vars);
|
||||
|
||||
return successResult;
|
||||
}
|
||||
@ -225,7 +227,7 @@ int getopt(int, char *const[], const char *);
|
||||
#endif
|
||||
|
||||
static void
|
||||
parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * options)
|
||||
parse_options(int argc, char *argv[], struct adhoc_opts * options)
|
||||
{
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static struct option long_options[] = {
|
||||
@ -234,9 +236,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
{"database", required_argument, NULL, 'd'},
|
||||
{"dbname", required_argument, NULL, 'd'},
|
||||
{"echo", no_argument, NULL, 'e'},
|
||||
{"echo-queries", no_argument, NULL, 'e'},
|
||||
{"echo-all", no_argument, NULL, 'E'},
|
||||
{"echo-all-queries", no_argument, NULL, 'E'},
|
||||
{"echo-hidden", no_argument, NULL, 'E'},
|
||||
{"file", required_argument, NULL, 'f'},
|
||||
{"field-separator", required_argument, NULL, 'F'},
|
||||
{"host", required_argument, NULL, 'h'},
|
||||
@ -261,12 +261,12 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
};
|
||||
|
||||
int optindex;
|
||||
|
||||
#endif
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
int c;
|
||||
bool used_old_u_option = false;
|
||||
|
||||
memset(options, 0, sizeof *options);
|
||||
|
||||
@ -284,7 +284,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
switch (c)
|
||||
{
|
||||
case 'A':
|
||||
pset->popt.topt.format = PRINT_UNALIGNED;
|
||||
pset.popt.topt.format = PRINT_UNALIGNED;
|
||||
break;
|
||||
case 'c':
|
||||
options->action_string = optarg;
|
||||
@ -297,23 +297,23 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
options->dbname = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
SetVariable(pset->vars, "echo", "");
|
||||
SetVariable(pset.vars, "ECHO", "full");
|
||||
break;
|
||||
case 'E':
|
||||
SetVariable(pset->vars, "echo_secret", "");
|
||||
SetVariable(pset.vars, "ECHO_HIDDEN", "");
|
||||
break;
|
||||
case 'f':
|
||||
options->action = ACT_FILE;
|
||||
options->action_string = optarg;
|
||||
break;
|
||||
case 'F':
|
||||
pset->popt.topt.fieldSep = strdup(optarg);
|
||||
pset.popt.topt.fieldSep = strdup(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
options->host = optarg;
|
||||
break;
|
||||
case 'H':
|
||||
pset->popt.topt.format = PRINT_HTML;
|
||||
pset.popt.topt.format = PRINT_HTML;
|
||||
break;
|
||||
case 'l':
|
||||
options->action = ACT_LIST_DB;
|
||||
@ -322,7 +322,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
options->no_readline = true;
|
||||
break;
|
||||
case 'o':
|
||||
setQFout(optarg, pset);
|
||||
setQFout(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
options->port = optarg;
|
||||
@ -336,16 +336,16 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
value = xstrdup(optarg);
|
||||
equal_loc = strchr(value, '=');
|
||||
if (!equal_loc)
|
||||
result = do_pset(value, NULL, &pset->popt, true);
|
||||
result = do_pset(value, NULL, &pset.popt, true);
|
||||
else
|
||||
{
|
||||
*equal_loc = '\0';
|
||||
result = do_pset(value, equal_loc + 1, &pset->popt, true);
|
||||
result = do_pset(value, equal_loc + 1, &pset.popt, true);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
fprintf(stderr, "Couldn't set printing paramter %s.\n", value);
|
||||
fprintf(stderr, "%s: couldn't set printing parameter %s\n", pset.progname, value);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -353,29 +353,31 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
break;
|
||||
}
|
||||
case 'q':
|
||||
SetVariable(pset->vars, "quiet", "");
|
||||
SetVariable(pset.vars, "QUIET", "");
|
||||
break;
|
||||
case 's':
|
||||
SetVariable(pset->vars, "singlestep", "");
|
||||
SetVariable(pset.vars, "SINGLESTEP", "");
|
||||
break;
|
||||
case 'S':
|
||||
SetVariable(pset->vars, "singleline", "");
|
||||
SetVariable(pset.vars, "SINGLELINE", "");
|
||||
break;
|
||||
case 't':
|
||||
pset->popt.topt.tuples_only = true;
|
||||
pset.popt.topt.tuples_only = true;
|
||||
break;
|
||||
case 'T':
|
||||
pset->popt.topt.tableAttr = xstrdup(optarg);
|
||||
pset.popt.topt.tableAttr = xstrdup(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
pset->getPassword = true;
|
||||
options->username = "?";
|
||||
pset.getPassword = true;
|
||||
options->username = "\001"; /* hopefully nobody has that username */
|
||||
/* this option is out */
|
||||
used_old_u_option = true;
|
||||
break;
|
||||
case 'U':
|
||||
options->username = optarg;
|
||||
break;
|
||||
case 'x':
|
||||
pset->popt.topt.expanded = true;
|
||||
pset.popt.topt.expanded = true;
|
||||
break;
|
||||
case 'v':
|
||||
{
|
||||
@ -386,20 +388,20 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
equal_loc = strchr(value, '=');
|
||||
if (!equal_loc)
|
||||
{
|
||||
if (!DeleteVariable(pset->vars, value))
|
||||
if (!DeleteVariable(pset.vars, value))
|
||||
{
|
||||
fprintf(stderr, "%s: could not delete variable %s\n",
|
||||
pset->progname, value);
|
||||
pset.progname, value);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*equal_loc = '\0';
|
||||
if (!SetVariable(pset->vars, value, equal_loc + 1))
|
||||
if (!SetVariable(pset.vars, value, equal_loc + 1))
|
||||
{
|
||||
fprintf(stderr, "%s: Couldn't set variable %s to %s\n",
|
||||
pset->progname, value, equal_loc);
|
||||
fprintf(stderr, "%s: could not set variable %s\n",
|
||||
pset.progname, value);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@ -411,7 +413,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
showVersion();
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'W':
|
||||
pset->getPassword = true;
|
||||
pset.getPassword = true;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
@ -420,7 +422,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
#ifndef HAVE_GETOPT_LONG
|
||||
case '-':
|
||||
fprintf(stderr, "%s was compiled without support for long options.\n"
|
||||
"Use -? for help on invocation options.\n", pset->progname);
|
||||
"Use -? for help on invocation options.\n", pset.progname);
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
#endif
|
||||
@ -441,12 +443,16 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
options->dbname = argv[optind];
|
||||
else if (!options->username)
|
||||
options->username = argv[optind];
|
||||
else
|
||||
else if (!QUIET())
|
||||
fprintf(stderr, "%s: warning: extra option %s ignored\n",
|
||||
pset->progname, argv[optind]);
|
||||
pset.progname, argv[optind]);
|
||||
|
||||
optind++;
|
||||
}
|
||||
|
||||
if (used_old_u_option && !QUIET())
|
||||
fprintf(stderr, "%s: Warning: The -u option is deprecated. Use -U.\n", pset.progname);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -455,7 +461,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
|
||||
* Load /etc/psqlrc or .psqlrc file, if found.
|
||||
*/
|
||||
static void
|
||||
process_psqlrc(PsqlSettings *pset)
|
||||
process_psqlrc(void)
|
||||
{
|
||||
char *psqlrc;
|
||||
char *home;
|
||||
@ -466,9 +472,9 @@ process_psqlrc(PsqlSettings *pset)
|
||||
|
||||
/* System-wide startup file */
|
||||
if (access("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, R_OK) == 0)
|
||||
process_file("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, pset);
|
||||
process_file("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION);
|
||||
else if (access("/etc/psqlrc", R_OK) == 0)
|
||||
process_file("/etc/psqlrc", pset);
|
||||
process_file("/etc/psqlrc");
|
||||
|
||||
/* Look for one in the home dir */
|
||||
home = getenv("HOME");
|
||||
@ -484,12 +490,12 @@ process_psqlrc(PsqlSettings *pset)
|
||||
|
||||
sprintf(psqlrc, "%s/.psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, home);
|
||||
if (access(psqlrc, R_OK) == 0)
|
||||
process_file(psqlrc, pset);
|
||||
process_file(psqlrc);
|
||||
else
|
||||
{
|
||||
sprintf(psqlrc, "%s/.psqlrc", home);
|
||||
if (access(psqlrc, R_OK) == 0)
|
||||
process_file(psqlrc, pset);
|
||||
process_file(psqlrc);
|
||||
}
|
||||
free(psqlrc);
|
||||
}
|
||||
@ -529,7 +535,7 @@ showVersion(void)
|
||||
#else
|
||||
#define _Feature
|
||||
#endif
|
||||
fputs("multibyte");
|
||||
fputs("multibyte", stdout);
|
||||
#endif
|
||||
|
||||
#undef _Feature
|
||||
|
Loading…
x
Reference in New Issue
Block a user