Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
7c9390ca
Commit
7c9390ca
authored
Jan 14, 2000
by
Peter Eisentraut
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed psql variables vs array syntax, as well as minor psql enhancements
parent
4ceb2d0c
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1005 additions
and
918 deletions
+1005
-918
doc/src/sgml/ref/psql-ref.sgml
doc/src/sgml/ref/psql-ref.sgml
+312
-234
src/bin/psql/command.c
src/bin/psql/command.c
+151
-121
src/bin/psql/command.h
src/bin/psql/command.h
+6
-7
src/bin/psql/common.c
src/bin/psql/common.c
+112
-200
src/bin/psql/common.h
src/bin/psql/common.h
+3
-6
src/bin/psql/copy.c
src/bin/psql/copy.c
+45
-40
src/bin/psql/copy.h
src/bin/psql/copy.h
+1
-1
src/bin/psql/describe.c
src/bin/psql/describe.c
+53
-49
src/bin/psql/describe.h
src/bin/psql/describe.h
+9
-9
src/bin/psql/help.c
src/bin/psql/help.c
+8
-7
src/bin/psql/help.h
src/bin/psql/help.h
+1
-1
src/bin/psql/input.c
src/bin/psql/input.c
+23
-4
src/bin/psql/input.h
src/bin/psql/input.h
+1
-1
src/bin/psql/large_obj.c
src/bin/psql/large_obj.c
+55
-55
src/bin/psql/large_obj.h
src/bin/psql/large_obj.h
+4
-5
src/bin/psql/mainloop.c
src/bin/psql/mainloop.c
+98
-60
src/bin/psql/mainloop.h
src/bin/psql/mainloop.h
+1
-3
src/bin/psql/prompt.c
src/bin/psql/prompt.c
+24
-25
src/bin/psql/prompt.h
src/bin/psql/prompt.h
+1
-1
src/bin/psql/settings.h
src/bin/psql/settings.h
+4
-2
src/bin/psql/startup.c
src/bin/psql/startup.c
+93
-87
No files found.
doc/src/sgml/ref/psql-ref.sgml
View file @
7c9390ca
<!--
<!--
$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
Postgres documentation
-->
-->
...
@@ -32,27 +32,20 @@ Postgres documentation
...
@@ -32,27 +32,20 @@ Postgres documentation
<date>1998-09-26</date>
<date>1998-09-26</date>
</refsect2info>
</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>.
</para>
</refsect2>
<refsect2 id="R2-APP-PSQL-2">
<refsect2info>
<date>1998-10-26</date>
</refsect2info>
<title>Output</title>
<para>
<para>
<application>psql</application> returns 0 to the shell on successful
<application>psql</application> is a terminal-based front-end to
completion of all queries, 1 for fatal errors, 2 for abrupt disconnection
<productname>PostgreSQL</productname>. It enables you to type in queries
from the backend, and 3 if a non-interactive script stopped because an <acronym>SQL</acronym>
interactively, issue them to <productname>PostgreSQL</productname>, and see
command or psql meta-command resulted in an error.
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>
</para>
</refsect2>
</refsect2>
</refsynopsisdiv>
</refsynopsisdiv>
<refsect1 id="R1-APP-PSQL-1">
<refsect1 id="R1-APP-PSQL-1">
...
@@ -62,58 +55,31 @@ Postgres documentation
...
@@ -62,58 +55,31 @@ Postgres documentation
<title>Description</title>
<title>Description</title>
<para>
<refsect2 id="R2-APP-PSQL-connecting">
<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">
<refsect2info>
<refsect2info>
<date>
1998-09-26
</date>
<date>
2000-01-14
</date>
</refsect2info>
</refsect2info>
<title>Connecting To A Database</title>
<title>Connecting To A Database</title>
<para>
<para>
<application>psql</application> attempts to make a connection to the
<application>psql</application> is a regular <productname>PostgreSQL</productname>
database name at the hostname and port number, and with the user name
client application. In order to connect to a database you need to determine
specified on the command line. If any of these are omitted, the
name of you target database, the hostname and port number of the server
<application>libpq</application> client library, upon which
and what user name you want to connect as. <application>psql</application> can be
<application>psql</application> is built, will choose defaults.
told about those parameters via command line options, namely <option>-d</option>,
(This will usually mean the environment variables <envar>PGDATABASE</envar>,
<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>,
<envar>PGHOST</envar>, <envar>PGPORT</envar>, <envar>PGUSER</envar>,
respectively, if they are set. Otherwise the default host is the local host
respectively to appropriate values.
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.)
</para>
</para>
<para>
<para>
...
@@ -151,8 +117,9 @@ testdb=>
...
@@ -151,8 +117,9 @@ testdb=>
<para>
<para>
At the prompt, the user may type in <acronym>SQL</acronym> queries.
At the prompt, the user may type in <acronym>SQL</acronym> queries.
Ordinarily, input lines are sent to the backend when a query-terminating
Ordinarily, input lines are sent to the backend when a query-terminating
semicolon is reached. If the database server reports success, the query
semicolon is reached. An end of line does not terminate a query! Thus queries
results are displayed on the screen.
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>
<para>
<para>
...
@@ -173,12 +140,11 @@ testdb=>
...
@@ -173,12 +140,11 @@ testdb=>
<para>
<para>
Anything you enter in <application>psql</application> that begins with an
Anything you enter in <application>psql</application> that begins with an
unquoted backslash is a <application>psql</application> meta-command.
unquoted backslash is a <application>psql</application> meta-command that is
Anything else is <acronym>SQL</acronym> and simply goes into the current
processes by <application>psql</application> itself.
query buffer (and once you have at least one complete query, it gets
These commands are what makes
automatically submitted to the backend). For this reason,
<application>psql</application> interesting for administration or scripting.
<application>psql</application> meta-commands are more commonly called
Meta-commands are more commonly called slash or backslash commands.
slash or backslash commands.
</para>
</para>
<para>
<para>
...
@@ -268,11 +234,8 @@ testdb=>
...
@@ -268,11 +234,8 @@ testdb=>
</para>
</para>
<para>
<para>
If <replaceable class="parameter">username</replaceable> is omitted or
If <replaceable class="parameter">username</replaceable> is omitted
<literal>-</literal> the current user name is assumed. If
the current user name is assumed.
<replaceable class="parameter">username</replaceable> is <literal>?</literal>
<application>psql</application> will prompt for the new user name
interactively.
</para>
</para>
<para>
<para>
...
@@ -293,10 +256,11 @@ testdb=>
...
@@ -293,10 +256,11 @@ testdb=>
</varlistentry>
</varlistentry>
<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> }
[ <literal>with oids</literal> ] { <literal>from</literal> | <literal>to</literal> }
<replaceable class="parameter">filename</replaceable> [ <literal>with delimiters</literal>
<replaceable class="parameter">filename</replaceable> | stdin | stdout
'<replaceable class="parameter">character</replaceable>' ]
[ <literal>with delimiters</literal> '<replaceable class="parameter">characters</replaceable>' ]
[ <literal>with null as</literal> '<replaceable class="parameter">string</replaceable>' ]
</term>
</term>
<listitem>
<listitem>
...
@@ -326,6 +290,18 @@ testdb=>
...
@@ -326,6 +290,18 @@ testdb=>
technique may be preferable.
technique may be preferable.
</para>
</para>
</tip>
</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>
</listitem>
</varlistentry>
</varlistentry>
...
@@ -666,7 +642,7 @@ Tue Oct 26 21:40:57 CEST 1999
...
@@ -666,7 +642,7 @@ Tue Oct 26 21:40:57 CEST 1999
</tip>
</tip>
<note>
<note>
<para>
<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.
important information concerning all large object operations.
</para>
</para>
</note>
</note>
...
@@ -689,7 +665,7 @@ lo_import 152801
...
@@ -689,7 +665,7 @@ lo_import 152801
which one ought to remember if one wants to access the object ever again.
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
For that reason it is recommended to always associate a human-readable
comment with every object. Those can then be seen with the
comment with every object. Those can then be seen with the
<command>\lo_list
?
</command> command.
<command>\lo_list</command> command.
</para>
</para>
<para>
<para>
...
@@ -700,7 +676,7 @@ lo_import 152801
...
@@ -700,7 +676,7 @@ lo_import 152801
<note>
<note>
<para>
<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.
important information concerning all large object operations.
</para>
</para>
</note>
</note>
...
@@ -733,7 +709,7 @@ lo_import 152801
...
@@ -733,7 +709,7 @@ lo_import 152801
</tip>
</tip>
<note>
<note>
<para>
<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.
important information concerning all large object operations.
</para>
</para>
</note>
</note>
...
@@ -755,9 +731,11 @@ lo_import 152801
...
@@ -755,9 +731,11 @@ lo_import 152801
</para>
</para>
<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
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>
</para>
<tip>
<tip>
...
@@ -922,7 +900,7 @@ lo_import 152801
...
@@ -922,7 +900,7 @@ lo_import 152801
<para>
<para>
Toggles the list of a pager to do table output. If the environment variable
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.
<envar>PAGER</envar> is set, the output is piped to the specified program.
Otherwise <filename>
/bin/more</filename> is assum
ed.
Otherwise <filename>
more</filename> is us
ed.
</para>
</para>
<para>
<para>
...
@@ -1024,10 +1002,8 @@ lo_import 152801
...
@@ -1024,10 +1002,8 @@ lo_import 152801
<para>
<para>
Sets the internal variable <replaceable class="parameter">name</replaceable>
Sets the internal variable <replaceable class="parameter">name</replaceable>
to <replaceable class="parameter">value</replaceable>. If no second argument
to <replaceable class="parameter">value</replaceable>. If no second argument
is given, the variable is unset (which is different from setting it to,
is given, the variable is just set with not value. To unset a variable, use
for example, an empty string: <literal>\set foo ''</literal>). If no
the <command>\unset</command> command.
arguments are given, all currently defined variables are listed with their
values.
</para>
</para>
<para>
<para>
...
@@ -1192,14 +1168,7 @@ Access permissions for database "test"
...
@@ -1192,14 +1168,7 @@ Access permissions for database "test"
<para>
<para>
If so configured, <application>psql</application> understands both standard
If so configured, <application>psql</application> understands both standard
Unix short options, and <acronym>GNU</acronym>-style long options. The latter
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
are not available on all systems.
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.
</para>
</para>
<para>
<para>
...
@@ -1221,8 +1190,7 @@ Access permissions for database "test"
...
@@ -1221,8 +1190,7 @@ Access permissions for database "test"
<para>
<para>
Specifies that <application>psql</application>
Specifies that <application>psql</application>
is to execute one query string, <replaceable class="parameter">query</replaceable>,
is to execute one query string, <replaceable class="parameter">query</replaceable>,
and then exit. This is useful for shell scripts, typically in
and then exit. This is useful for shell scripts.
conjunction with the <option>-q</option> option.
</para>
</para>
<para>
<para>
<replaceable class="parameter">query</replaceable> must be either a query string
<replaceable class="parameter">query</replaceable> must be either a query string
...
@@ -1254,20 +1222,20 @@ Access permissions for database "test"
...
@@ -1254,20 +1222,20 @@ Access permissions for database "test"
<listitem>
<listitem>
<para>
<para>
In non-interactive mode, all lines are printed to the screen as they are read.
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>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
<varlistentry>
<varlistentry>
<term>-E, --echo-
all
</term>
<term>-E, --echo-
hidden
</term>
<listitem>
<listitem>
<para>
<para>
Echos the actual queries generated by \d and other backslash commands.
Echos the actual queries generated by \d and other backslash commands.
You can use this if you wish to include similar functionality into
You can use this if you wish to include similar functionality into
your own programs. This is equivalent to setting the variable
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>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
...
@@ -1337,7 +1305,7 @@ Access permissions for database "test"
...
@@ -1337,7 +1305,7 @@ Access permissions for database "test"
<term>-n, --no-readline</term>
<term>-n, --no-readline</term>
<listitem>
<listitem>
<para>
<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>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
...
@@ -1389,7 +1357,7 @@ Access permissions for database "test"
...
@@ -1389,7 +1357,7 @@ Access permissions for database "test"
By default, it prints welcome messages and various informational output.
By default, it prints welcome messages and various informational output.
If this option is used, none of this happens. This is useful with the
If this option is used, none of this happens. This is useful with the
<option>-c</option> option. Within <application>psql</application> you can
<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>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
...
@@ -1411,7 +1379,7 @@ Access permissions for database "test"
...
@@ -1411,7 +1379,7 @@ Access permissions for database "test"
<term>-S, --single-line</term>
<term>-S, --single-line</term>
<listitem>
<listitem>
<para>
<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>
</para>
<note>
<note>
...
@@ -1419,8 +1387,7 @@ Access permissions for database "test"
...
@@ -1419,8 +1387,7 @@ Access permissions for database "test"
This mode is provided for those who insist on it, but you are not necessarily
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
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
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,
the unexperienced user.
avoid using this mode.
</para>
</para>
</note>
</note>
</listitem>
</listitem>
...
@@ -1472,9 +1439,7 @@ Access permissions for database "test"
...
@@ -1472,9 +1439,7 @@ Access permissions for database "test"
<listitem>
<listitem>
<para>
<para>
Connects to the database as the user <replaceable class="parameter">username</replaceable>
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
instead of the default. (You must have permission to do so, of course.)
<replaceable class="parameter">username</replaceable> is <quote>?</quote>, <application>psql</application>
issues an interactive prompt for the user name.
</para>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
...
@@ -1486,7 +1451,9 @@ Access permissions for database "test"
...
@@ -1486,7 +1451,9 @@ Access permissions for database "test"
<para>
<para>
Performs a variable assignment, like the <command>\set</command> internal command.
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
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>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
...
@@ -1503,7 +1470,7 @@ Access permissions for database "test"
...
@@ -1503,7 +1470,7 @@ Access permissions for database "test"
<varlistentry>
<varlistentry>
<term>-W</term>
<term>-W
, --password
</term>
<listitem>
<listitem>
<para>
<para>
Requests that <application>psql</application> should prompt for a password
Requests that <application>psql</application> should prompt for a password
...
@@ -1518,26 +1485,28 @@ Access permissions for database "test"
...
@@ -1518,26 +1485,28 @@ Access permissions for database "test"
Because this is currently based on a <quote>hack</quote> the automatic
Because this is currently based on a <quote>hack</quote> the automatic
recognition might mysteriously fail, hence this option to force a prompt.
recognition might mysteriously fail, hence this option to force a prompt.
If no password prompt is issued and the backend requires password authentication
If no password prompt is issued and the backend requires password authentication
the content of the environment variable <envar>PGPASSWORD</envar> is
the connection attempt will fail.
taken. If this is not set, the connection attempt will fail.
</para>
</para>
</listitem>
</varlistentry>
<caution>
<varlistentry>
<term>-x, --expanded</term>
<listitem>
<para>
<para>
If you are considering setting the variable <envar>PGPASSWORD</envar> to do
Turns on extended row format mode. This is equivalent to the command
authentication, you have a problem
.
<command>\x</command>
.
</para>
</para>
</caution>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
<varlistentry>
<varlistentry>
<term>-
x
</term>
<term>-
?, --help
</term>
<listitem>
<listitem>
<para>
<para>
Turns on extended row format mode. This is equivalent to the command
Shows help about <application>psql</application> command line arguments.
<command>\x</command>.
</para>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
...
@@ -1545,12 +1514,6 @@ Access permissions for database "test"
...
@@ -1545,12 +1514,6 @@ Access permissions for database "test"
</variablelist>
</variablelist>
</para>
</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>
</refsect1>
...
@@ -1585,7 +1548,7 @@ bar
...
@@ -1585,7 +1548,7 @@ bar
testdb=> <userinput>\echo "foo is now ${foo}."</userinput>
testdb=> <userinput>\echo "foo is now ${foo}."</userinput>
foo is now bar.
foo is now bar.
</programlisting>
</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
will be performed in single-quoted strings or in any of the backslash commands
that have special parsing rules (e.g., <command>\copy</command>).
that have special parsing rules (e.g., <command>\copy</command>).
</para>
</para>
...
@@ -1605,52 +1568,70 @@ foo is now bar.
...
@@ -1605,52 +1568,70 @@ foo is now bar.
</note>
</note>
<para>
<para>
<application>psql</application>'s internal variable names can consist of
If you call <command>\set</command> without an argument, the variable is simply
letters, numbers, and underscores in any order and any number of them.
set, but has no value. To unset (or delete) a variable, use the command
It is recommended, however, that you stick to lower-case letters and do not
<command>\unset</command>.
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>
<para>
<para>
<application>psql</application>'s internal variable names can consist of
letters, numbers, and underscores in any order and any number of them.
A number of regular variables are treated specially by <application>psql</application>.
A number of regular variables are treated specially by <application>psql</application>.
They indicate certain option settings that can be changed at runtime
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
variables for any other purpose, this is not recommended, as the
program behavior might grow really strange really quickly. Note that the
program behavior might grow really strange really quickly.
majority variables are <quote>boolean</quote> variables, that is, they
By convention, all specially treated variables consist of all upper-case letters
only care whether or not are they set, not what to. A list of all specially
(and possibly numbers and underscores). To ensure maximum compatibility in the
treated variables follows.
future, avoid such variables.
A list of all specially treated variables follows.
<variablelist>
<variablelist>
<varlistentry>
<varlistentry>
<term><envar>die_on_error</envar></term>
<term><envar>DBNAME</envar></term>
<listitem>
<para>
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>
<listitem>
<para>
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_HIDDEN</envar></term>
<listitem>
<para>
When this variable is set and a backslash command queries the database, the query
is first shown. This way you can study the <productname>PostgreSQL</productname>
internals and provide similar functionality in your own programs. If you set the
variable to the value <quote>noexec</quote>, the queries are just shown but are
not actually sent to the backend and executed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><envar>EXIT_ON_ERROR</envar></term>
<listitem>
<listitem>
<para>
<para>
By default, if non-interactive scripts encounter an error, such as a
By default, if non-interactive scripts encounter an error, such as a
malformed <acronym>SQL</acronym> query or internal meta-command,
malformed <acronym>SQL</acronym> query or internal meta-command,
processing continues. This is often less than desirable. If this variable
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
is set, script processing will immediately terminate. If the script was
called from another script it will terminate in the same fashion.
called from another script it will terminate in the same fashion.
If the outermost script was not called from an interactive <application>psql</application>
If the outermost script was not called from an interactive <application>psql</application>
...
@@ -1662,31 +1643,80 @@ foo is now bar.
...
@@ -1662,31 +1643,80 @@ foo is now bar.
</varlistentry>
</varlistentry>
<varlistentry>
<varlistentry>
<term><envar>
echo
</envar></term>
<term><envar>
HISTCONTROL
</envar></term>
<listitem>
<listitem>
<para>
<para>
If set, all lines from a script are written to the standard output before they
If this variable is set to <literal>ignorespace</literal>, lines which begin with a
are executed. To specify this on program startup, in conjunction with the
space are not entered into the history list. If set to a value of
<option>-f</option> option perhaps, use the switch <option>-e</option>.
<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>
</para>
<note>
<para>
This feature was shamelessly plagiarized from <application>bash</application>.
</para>
</note>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
<varlistentry>
<varlistentry>
<term><envar>
echo_secret
</envar></term>
<term><envar>
HISTSIZE
</envar></term>
<listitem>
<listitem>
<para>
<para>
When this variable is set and a backslash command queries the database, the query
The number of commands to store in the command history.
is first shown. This way you can study the <productname>PostgreSQL</productname>
The default value is 500.
internals and provide similar functionality in your own programs. If you set the
</para>
variable to the value <quote>noexec</quote>, the queries are just shown but are
<note>
not actually sent to the backend and executed.
<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>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
<varlistentry>
<varlistentry>
<term><envar>
lo_transaction
</envar></term>
<term><envar>
LO_TRANSACTION
</envar></term>
<listitem>
<listitem>
<para>
<para>
If you use the <productname>PostgreSQL</productname> large object
If you use the <productname>PostgreSQL</productname> large object
...
@@ -1702,7 +1732,7 @@ foo is now bar.
...
@@ -1702,7 +1732,7 @@ foo is now bar.
all. In the latter case you must provide you own
all. In the latter case you must provide you own
<command>BEGIN TRANSACTION</command>/<command>COMMIT</command> block or
<command>BEGIN TRANSACTION</command>/<command>COMMIT</command> block or
the results will be unpredictable (usually resulting in the desired
the results will be unpredictable (usually resulting in the desired
action not being performed
anyway
).
action not being performed
in any case
).
</para>
</para>
<para>
<para>
...
@@ -1717,7 +1747,17 @@ foo is now bar.
...
@@ -1717,7 +1747,17 @@ foo is now bar.
</varlistentry>
</varlistentry>
<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>
<listitem>
<para>
<para>
These specify what the prompt <application>psql</application> issues is
These specify what the prompt <application>psql</application> issues is
...
@@ -1729,7 +1769,7 @@ foo is now bar.
...
@@ -1729,7 +1769,7 @@ foo is now bar.
</varlistentry>
</varlistentry>
<varlistentry>
<varlistentry>
<term><envar>
quiet
</envar></term>
<term><envar>
QUIET
</envar></term>
<listitem>
<listitem>
<para>
<para>
This variable is equivalent to the command line option <option>-q</option>.
This variable is equivalent to the command line option <option>-q</option>.
...
@@ -1739,7 +1779,7 @@ foo is now bar.
...
@@ -1739,7 +1779,7 @@ foo is now bar.
</varlistentry>
</varlistentry>
<varlistentry>
<varlistentry>
<term><envar>
singleline
</envar></term>
<term><envar>
SINGLELINE
</envar></term>
<listitem>
<listitem>
<para>
<para>
This variable is set be the command line options <option>-S</option>. You
This variable is set be the command line options <option>-S</option>. You
...
@@ -1749,13 +1789,24 @@ foo is now bar.
...
@@ -1749,13 +1789,24 @@ foo is now bar.
</varlistentry>
</varlistentry>
<varlistentry>
<varlistentry>
<term><envar>
singlestep
</envar></term>
<term><envar>
SINGLESTEP
</envar></term>
<listitem>
<listitem>
<para>
<para>
This variable is equivalent to the command line option <option>-s</option>.
This variable is equivalent to the command line option <option>-s</option>.
</para>
</para>
</listitem>
</listitem>
</varlistentry>
</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>
</variablelist>
</para>
</para>
...
@@ -1814,6 +1865,15 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
...
@@ -1814,6 +1865,15 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
be better off preparing the file externally.
be better off preparing the file externally.
</para>
</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>
</refsect2>
...
@@ -1822,8 +1882,8 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
...
@@ -1822,8 +1882,8 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
<para>
<para>
The prompts <application>psql</application> issues can be customized to
The prompts <application>psql</application> issues can be customized to
your preference. The three variables <envar>
prompt1</envar>, <envar>prompt
2</envar>,
your preference. The three variables <envar>
PROMPT1</envar>, <envar>PROMPT
2</envar>,
and <envar>
prompt
3</envar> contain strings and special escape sequences
and <envar>
PROMPT
3</envar> contain strings and special escape sequences
that describe the appearance of the prompt. Prompt 1 is the normal prompt
that describe the appearance of the prompt. Prompt 1 is the normal prompt
that is issued when <application>psql</application> requests a new query.
that is issued when <application>psql</application> requests a new query.
Prompt 2 is issued when more input is expected during query input because
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
...
@@ -1924,8 +1984,75 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
and 2, and <literal>'>> '</literal> for prompt 3.
and 2, and <literal>'>> '</literal> for prompt 3.
</para>
</para>
<note>
<para>
This feature was shamelessly plagiarized from <application>tcsh</application>.
</para>
</note>
</refsect2>
</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>
</refsect1>
...
@@ -2074,23 +2201,9 @@ Field separator is "oo".
...
@@ -2074,23 +2201,9 @@ Field separator is "oo".
<listitem>
<listitem>
<para>
<para>
There are about three different parsers in <application>psql</application>,
<application>psql</application> only works smootly with servers of the
in addition to the backend <acronym>SQL</acronym> parser, all doing their own thing
same version. That does not mean other combinations will fail outright,
and attempting to get along with each other. Sometimes they do, sometimes
but subtle and not-so-subtle problems might come up.
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.
</para>
</para>
</listitem>
</listitem>
...
@@ -2098,7 +2211,7 @@ Field separator is "oo".
...
@@ -2098,7 +2211,7 @@ Field separator is "oo".
<para>
<para>
The number of options for a backslash command is limited, probably to 16.
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
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.
that actually uses that many options though.
</para>
</para>
</listitem>
</listitem>
...
@@ -2106,41 +2219,6 @@ Field separator is "oo".
...
@@ -2106,41 +2219,6 @@ Field separator is "oo".
</refsect2>
</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>
</refsect1>
</refentry>
</refentry>
...
...
src/bin/psql/command.c
View file @
7c9390ca
#include <config.h>
#include <c.h>
#include <c.h>
#include "command.h"
#include "command.h"
...
@@ -26,6 +25,7 @@
...
@@ -26,6 +25,7 @@
#include "print.h"
#include "print.h"
#include "describe.h"
#include "describe.h"
#include "input.h"
#include "input.h"
#include "variables.h"
#ifdef WIN32
#ifdef WIN32
#define popen(x,y) _popen(x,y)
#define popen(x,y) _popen(x,y)
...
@@ -38,16 +38,14 @@
...
@@ -38,16 +38,14 @@
static
backslashResult
exec_command
(
const
char
*
cmd
,
static
backslashResult
exec_command
(
const
char
*
cmd
,
char
*
const
*
options
,
char
*
const
*
options
,
const
char
*
options_string
,
const
char
*
options_string
,
PQExpBuffer
query_buf
,
PQExpBuffer
query_buf
);
PsqlSettings
*
pset
);
static
bool
do_edit
(
const
char
*
filename_arg
,
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
,
static
bool
do_connect
(
const
char
*
new_dbname
,
const
char
*
new_user
,
const
char
*
new_user
);
PsqlSettings
*
pset
);
static
bool
do_shell
(
const
char
*
command
);
static
bool
do_shell
(
const
char
*
command
);
...
@@ -79,8 +77,7 @@ static bool do_shell(const char *command);
...
@@ -79,8 +77,7 @@ static bool do_shell(const char *command);
*/
*/
backslashResult
backslashResult
HandleSlashCmds
(
PsqlSettings
*
pset
,
HandleSlashCmds
(
const
char
*
line
,
const
char
*
line
,
PQExpBuffer
query_buf
,
PQExpBuffer
query_buf
,
const
char
**
end_of_cmd
)
const
char
**
end_of_cmd
)
{
{
...
@@ -95,6 +92,12 @@ HandleSlashCmds(PsqlSettings *pset,
...
@@ -95,6 +92,12 @@ HandleSlashCmds(PsqlSettings *pset,
const
char
*
continue_parse
=
NULL
;
/* tell the mainloop where the
const
char
*
continue_parse
=
NULL
;
/* tell the mainloop where the
* backslash command ended */
* backslash command ended */
#ifdef USE_ASSERT_CHECKING
assert
(
line
);
assert
(
query_buf
);
assert
(
end_of_cmd
);
#endif
my_line
=
xstrdup
(
line
);
my_line
=
xstrdup
(
line
);
/*
/*
...
@@ -135,7 +138,7 @@ HandleSlashCmds(PsqlSettings *pset,
...
@@ -135,7 +138,7 @@ HandleSlashCmds(PsqlSettings *pset,
switch
(
quote
)
switch
(
quote
)
{
{
case
'"'
:
case
'"'
:
options
[
i
]
=
unescape
(
token
,
pset
);
options
[
i
]
=
unescape
(
token
);
break
;
break
;
case
'\''
:
case
'\''
:
options
[
i
]
=
xstrdup
(
token
);
options
[
i
]
=
xstrdup
(
token
);
...
@@ -144,7 +147,7 @@ HandleSlashCmds(PsqlSettings *pset,
...
@@ -144,7 +147,7 @@ HandleSlashCmds(PsqlSettings *pset,
{
{
bool
error
=
false
;
bool
error
=
false
;
FILE
*
fd
=
NULL
;
FILE
*
fd
=
NULL
;
char
*
file
=
unescape
(
token
,
pset
);
char
*
file
=
unescape
(
token
);
PQExpBufferData
output
;
PQExpBufferData
output
;
char
buf
[
512
];
char
buf
[
512
];
size_t
result
;
size_t
result
;
...
@@ -200,8 +203,13 @@ HandleSlashCmds(PsqlSettings *pset,
...
@@ -200,8 +203,13 @@ HandleSlashCmds(PsqlSettings *pset,
default:
default:
if
(
token
[
0
]
==
'\\'
)
if
(
token
[
0
]
==
'\\'
)
continue_parse
=
options_string
+
pos
;
continue_parse
=
options_string
+
pos
;
else
if
(
token
[
0
]
==
'$'
)
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
else
options
[
i
]
=
xstrdup
(
token
);
options
[
i
]
=
xstrdup
(
token
);
}
}
...
@@ -216,7 +224,7 @@ HandleSlashCmds(PsqlSettings *pset,
...
@@ -216,7 +224,7 @@ HandleSlashCmds(PsqlSettings *pset,
}
}
cmd
=
my_line
;
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
)
if
(
status
==
CMD_UNKNOWN
)
{
{
...
@@ -238,15 +246,15 @@ HandleSlashCmds(PsqlSettings *pset,
...
@@ -238,15 +246,15 @@ HandleSlashCmds(PsqlSettings *pset,
new_cmd
[
0
]
=
cmd
[
0
];
new_cmd
[
0
]
=
cmd
[
0
];
new_cmd
[
1
]
=
'\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
(
status
==
CMD_UNKNOWN
)
{
{
if
(
pset
->
cur_cmd_interactive
)
if
(
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"Invalid command
\\
%s. Try
\\
? for help.
\n
"
,
cmd
);
fprintf
(
stderr
,
"Invalid command
\\
%s. Try
\\
? for help.
\n
"
,
cmd
);
else
else
fprintf
(
stderr
,
"%s: invalid command
\\
%s"
,
pset
->
progname
,
cmd
);
fprintf
(
stderr
,
"%s: invalid command
\\
%s"
,
pset
.
progname
,
cmd
);
status
=
CMD_ERROR
;
status
=
CMD_ERROR
;
}
}
...
@@ -254,13 +262,10 @@ HandleSlashCmds(PsqlSettings *pset,
...
@@ -254,13 +262,10 @@ HandleSlashCmds(PsqlSettings *pset,
continue_parse
+=
2
;
continue_parse
+=
2
;
if
(
end_of_cmd
)
if
(
continue_parse
)
{
*
end_of_cmd
=
line
+
(
continue_parse
-
my_line
);
if
(
continue_parse
)
else
*
end_of_cmd
=
line
+
(
continue_parse
-
my_line
);
*
end_of_cmd
=
line
+
strlen
(
line
);
else
*
end_of_cmd
=
NULL
;
}
/* clean up */
/* clean up */
for
(
i
=
0
;
i
<
NR_OPTIONS
&&
options
[
i
];
i
++
)
for
(
i
=
0
;
i
<
NR_OPTIONS
&&
options
[
i
];
i
++
)
...
@@ -278,12 +283,11 @@ static backslashResult
...
@@ -278,12 +283,11 @@ static backslashResult
exec_command
(
const
char
*
cmd
,
exec_command
(
const
char
*
cmd
,
char
*
const
*
options
,
char
*
const
*
options
,
const
char
*
options_string
,
const
char
*
options_string
,
PQExpBuffer
query_buf
,
PQExpBuffer
query_buf
)
PsqlSettings
*
pset
)
{
{
bool
success
=
true
;
/* indicate here if the command ran ok or
bool
success
=
true
;
/* indicate here if the command ran ok or
* failed */
* failed */
bool
quiet
=
GetVariableBool
(
pset
->
vars
,
"quiet"
);
bool
quiet
=
QUIET
(
);
backslashResult
status
=
CMD_SKIP_LINE
;
backslashResult
status
=
CMD_SKIP_LINE
;
...
@@ -291,16 +295,16 @@ exec_command(const char *cmd,
...
@@ -291,16 +295,16 @@ exec_command(const char *cmd,
/* \a -- toggle field alignment This makes little sense but we keep it around. */
/* \a -- toggle field alignment This makes little sense but we keep it around. */
if
(
strcmp
(
cmd
,
"a"
)
==
0
)
if
(
strcmp
(
cmd
,
"a"
)
==
0
)
{
{
if
(
pset
->
popt
.
topt
.
format
!=
PRINT_ALIGNED
)
if
(
pset
.
popt
.
topt
.
format
!=
PRINT_ALIGNED
)
success
=
do_pset
(
"format"
,
"aligned"
,
&
pset
->
popt
,
quiet
);
success
=
do_pset
(
"format"
,
"aligned"
,
&
pset
.
popt
,
quiet
);
else
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) */
/* \C -- override table title (formerly change HTML caption) */
else
if
(
strcmp
(
cmd
,
"C"
)
==
0
)
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,
...
@@ -316,25 +320,25 @@ exec_command(const char *cmd,
{
{
if
(
options
[
1
])
if
(
options
[
1
])
/* gave username */
/* gave username */
success
=
do_connect
(
options
[
0
],
options
[
1
]
,
pset
);
success
=
do_connect
(
options
[
0
],
options
[
1
]);
else
else
{
{
if
(
options
[
0
])
if
(
options
[
0
])
/* gave database name */
/* 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,
* username as before,
* NULL would mean libpq
* NULL would mean libpq
* default */
* default */
else
else
/* connect to default db as default user */
/* connect to default db as default user */
success
=
do_connect
(
NULL
,
NULL
,
pset
);
success
=
do_connect
(
NULL
,
NULL
);
}
}
}
}
/* \copy */
/* \copy */
else
if
(
strcmp
(
cmd
,
"copy"
)
==
0
)
else
if
(
strc
asec
mp
(
cmd
,
"copy"
)
==
0
)
success
=
do_copy
(
options_string
,
pset
);
success
=
do_copy
(
options_string
);
/* \copyright */
/* \copyright */
else
if
(
strcmp
(
cmd
,
"copyright"
)
==
0
)
else
if
(
strcmp
(
cmd
,
"copyright"
)
==
0
)
...
@@ -350,31 +354,31 @@ exec_command(const char *cmd,
...
@@ -350,31 +354,31 @@ exec_command(const char *cmd,
case
'\0'
:
case
'\0'
:
case
'?'
:
case
'?'
:
if
(
options
[
0
])
if
(
options
[
0
])
success
=
describeTableDetails
(
options
[
0
],
pset
,
show_verbose
);
success
=
describeTableDetails
(
options
[
0
],
show_verbose
);
else
else
/* standard listing of interesting things */
/* standard listing of interesting things */
success
=
listTables
(
"tvs"
,
NULL
,
pset
,
show_verbose
);
success
=
listTables
(
"tvs"
,
NULL
,
show_verbose
);
break
;
break
;
case
'a'
:
case
'a'
:
success
=
describeAggregates
(
options
[
0
]
,
pset
);
success
=
describeAggregates
(
options
[
0
]);
break
;
break
;
case
'd'
:
case
'd'
:
success
=
objectDescription
(
options
[
0
]
,
pset
);
success
=
objectDescription
(
options
[
0
]);
break
;
break
;
case
'f'
:
case
'f'
:
success
=
describeFunctions
(
options
[
0
],
pset
,
show_verbose
);
success
=
describeFunctions
(
options
[
0
],
show_verbose
);
break
;
break
;
case
'l'
:
case
'l'
:
success
=
do_lo_list
(
pset
);
success
=
do_lo_list
();
break
;
break
;
case
'o'
:
case
'o'
:
success
=
describeOperators
(
options
[
0
]
,
pset
);
success
=
describeOperators
(
options
[
0
]);
break
;
break
;
case
'p'
:
case
'p'
:
success
=
permissionsList
(
options
[
0
]
,
pset
);
success
=
permissionsList
(
options
[
0
]);
break
;
break
;
case
'T'
:
case
'T'
:
success
=
describeTypes
(
options
[
0
],
pset
,
show_verbose
);
success
=
describeTypes
(
options
[
0
],
show_verbose
);
break
;
break
;
case
't'
:
case
't'
:
case
'v'
:
case
'v'
:
...
@@ -382,9 +386,9 @@ exec_command(const char *cmd,
...
@@ -382,9 +386,9 @@ exec_command(const char *cmd,
case
's'
:
case
's'
:
case
'S'
:
case
'S'
:
if
(
cmd
[
1
]
==
'S'
&&
cmd
[
2
]
==
'\0'
)
if
(
cmd
[
1
]
==
'S'
&&
cmd
[
2
]
==
'\0'
)
success
=
listTables
(
"Stvs"
,
NULL
,
pset
,
show_verbose
);
success
=
listTables
(
"Stvs"
,
NULL
,
show_verbose
);
else
else
success
=
listTables
(
&
cmd
[
1
],
options
[
0
],
pset
,
show_verbose
);
success
=
listTables
(
&
cmd
[
1
],
options
[
0
],
show_verbose
);
break
;
break
;
default:
default:
status
=
CMD_UNKNOWN
;
status
=
CMD_UNKNOWN
;
...
@@ -412,15 +416,15 @@ exec_command(const char *cmd,
...
@@ -412,15 +416,15 @@ exec_command(const char *cmd,
/* \f -- change field separator */
/* \f -- change field separator */
else
if
(
strcmp
(
cmd
,
"f"
)
==
0
)
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 */
/* \g means send query */
else
if
(
strcmp
(
cmd
,
"g"
)
==
0
)
else
if
(
strcmp
(
cmd
,
"g"
)
==
0
)
{
{
if
(
!
options
[
0
])
if
(
!
options
[
0
])
pset
->
gfname
=
NULL
;
pset
.
gfname
=
NULL
;
else
else
pset
->
gfname
=
xstrdup
(
options
[
0
]);
pset
.
gfname
=
xstrdup
(
options
[
0
]);
status
=
CMD_SEND
;
status
=
CMD_SEND
;
}
}
...
@@ -442,10 +446,10 @@ exec_command(const char *cmd,
...
@@ -442,10 +446,10 @@ exec_command(const char *cmd,
/* HTML mode */
/* HTML mode */
else
if
(
strcmp
(
cmd
,
"H"
)
==
0
||
strcmp
(
cmd
,
"html"
)
==
0
)
else
if
(
strcmp
(
cmd
,
"H"
)
==
0
||
strcmp
(
cmd
,
"html"
)
==
0
)
{
{
if
(
pset
->
popt
.
topt
.
format
!=
PRINT_HTML
)
if
(
pset
.
popt
.
topt
.
format
!=
PRINT_HTML
)
success
=
do_pset
(
"format"
,
"html"
,
&
pset
->
popt
,
quiet
);
success
=
do_pset
(
"format"
,
"html"
,
&
pset
.
popt
,
quiet
);
else
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,
...
@@ -454,22 +458,22 @@ exec_command(const char *cmd,
{
{
if
(
!
options
[
0
])
if
(
!
options
[
0
])
{
{
if
(
pset
->
cur_cmd_interactive
)
if
(
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"
\\
%s: missing required argument
\n
"
,
cmd
);
fprintf
(
stderr
,
"
\\
%s: missing required argument
\n
"
,
cmd
);
else
else
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
->
progname
,
cmd
);
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
.
progname
,
cmd
);
success
=
false
;
success
=
false
;
}
}
else
else
success
=
process_file
(
options
[
0
]
,
pset
);
success
=
process_file
(
options
[
0
]);
}
}
/* \l is list databases */
/* \l is list databases */
else
if
(
strcmp
(
cmd
,
"l"
)
==
0
||
strcmp
(
cmd
,
"list"
)
==
0
)
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
)
else
if
(
strcmp
(
cmd
,
"l+"
)
==
0
||
strcmp
(
cmd
,
"list+"
)
==
0
)
success
=
listAllDbs
(
pset
,
true
);
success
=
listAllDbs
(
true
);
/* large object things */
/* large object things */
...
@@ -479,45 +483,45 @@ exec_command(const char *cmd,
...
@@ -479,45 +483,45 @@ exec_command(const char *cmd,
{
{
if
(
!
options
[
1
])
if
(
!
options
[
1
])
{
{
if
(
pset
->
cur_cmd_interactive
)
if
(
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"
\\
%s: missing required argument"
,
cmd
);
fprintf
(
stderr
,
"
\\
%s: missing required argument"
,
cmd
);
else
else
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
->
progname
,
cmd
);
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
.
progname
,
cmd
);
success
=
false
;
success
=
false
;
}
}
else
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
)
else
if
(
strcmp
(
cmd
+
3
,
"import"
)
==
0
)
{
{
if
(
!
options
[
0
])
if
(
!
options
[
0
])
{
{
if
(
pset
->
cur_cmd_interactive
)
if
(
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"
\\
%s: missing required argument"
,
cmd
);
fprintf
(
stderr
,
"
\\
%s: missing required argument"
,
cmd
);
else
else
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
->
progname
,
cmd
);
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
.
progname
,
cmd
);
success
=
false
;
success
=
false
;
}
}
else
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
)
else
if
(
strcmp
(
cmd
+
3
,
"list"
)
==
0
)
success
=
do_lo_list
(
pset
);
success
=
do_lo_list
();
else
if
(
strcmp
(
cmd
+
3
,
"unlink"
)
==
0
)
else
if
(
strcmp
(
cmd
+
3
,
"unlink"
)
==
0
)
{
{
if
(
!
options
[
0
])
if
(
!
options
[
0
])
{
{
if
(
pset
->
cur_cmd_interactive
)
if
(
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"
\\
%s: missing required argument"
,
cmd
);
fprintf
(
stderr
,
"
\\
%s: missing required argument"
,
cmd
);
else
else
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
->
progname
,
cmd
);
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
.
progname
,
cmd
);
success
=
false
;
success
=
false
;
}
}
else
else
success
=
do_lo_unlink
(
pset
,
options
[
0
]);
success
=
do_lo_unlink
(
options
[
0
]);
}
}
else
else
...
@@ -526,7 +530,7 @@ exec_command(const char *cmd,
...
@@ -526,7 +530,7 @@ exec_command(const char *cmd,
/* \o -- set query output */
/* \o -- set query output */
else
if
(
strcmp
(
cmd
,
"o"
)
==
0
||
strcmp
(
cmd
,
"out"
)
==
0
)
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 */
/* \p prints the current query buffer */
...
@@ -544,14 +548,14 @@ exec_command(const char *cmd,
...
@@ -544,14 +548,14 @@ exec_command(const char *cmd,
{
{
if
(
!
options
[
0
])
if
(
!
options
[
0
])
{
{
if
(
pset
->
cur_cmd_interactive
)
if
(
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"
\\
%s: missing required argument"
,
cmd
);
fprintf
(
stderr
,
"
\\
%s: missing required argument"
,
cmd
);
else
else
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
->
progname
,
cmd
);
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
.
progname
,
cmd
);
success
=
false
;
success
=
false
;
}
}
else
else
success
=
do_pset
(
options
[
0
],
options
[
1
],
&
pset
->
popt
,
quiet
);
success
=
do_pset
(
options
[
0
],
options
[
1
],
&
pset
.
popt
,
quiet
);
}
}
/* \q or \quit */
/* \q or \quit */
...
@@ -564,8 +568,8 @@ exec_command(const char *cmd,
...
@@ -564,8 +568,8 @@ exec_command(const char *cmd,
int
i
;
int
i
;
for
(
i
=
0
;
i
<
16
&&
options
[
i
];
i
++
)
for
(
i
=
0
;
i
<
16
&&
options
[
i
];
i
++
)
fputs
(
options
[
i
],
pset
->
queryFout
);
fputs
(
options
[
i
],
pset
.
queryFout
);
fputs
(
"
\n
"
,
pset
->
queryFout
);
fputs
(
"
\n
"
,
pset
.
queryFout
);
}
}
/* reset(clear) the buffer */
/* reset(clear) the buffer */
...
@@ -607,18 +611,21 @@ exec_command(const char *cmd,
...
@@ -607,18 +611,21 @@ exec_command(const char *cmd,
*/
*/
struct
_variable
*
ptr
;
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
);
fprintf
(
stdout
,
"%s = '%s'
\n
"
,
ptr
->
next
->
name
,
ptr
->
next
->
value
);
success
=
true
;
success
=
true
;
}
}
else
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
)
if
(
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"
\\
%s:
failed
\n
"
,
cmd
);
fprintf
(
stderr
,
"
\\
%s:
error
\n
"
,
cmd
);
else
else
fprintf
(
stderr
,
"%s:
\\
%s:
failed
\n
"
,
pset
->
progname
,
cmd
);
fprintf
(
stderr
,
"%s:
\\
%s:
error
\n
"
,
pset
.
progname
,
cmd
);
success
=
false
;
success
=
false
;
}
}
...
@@ -627,13 +634,26 @@ exec_command(const char *cmd,
...
@@ -627,13 +634,26 @@ exec_command(const char *cmd,
/* \t -- turn off headers and row count */
/* \t -- turn off headers and row count */
else
if
(
strcmp
(
cmd
,
"t"
)
==
0
)
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 */
/* \T -- define html <table ...> attributes */
else
if
(
strcmp
(
cmd
,
"T"
)
==
0
)
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 */
/* \w -- write query buffer to file */
else
if
(
strcmp
(
cmd
,
"w"
)
==
0
||
strcmp
(
cmd
,
"write"
)
==
0
)
else
if
(
strcmp
(
cmd
,
"w"
)
==
0
||
strcmp
(
cmd
,
"write"
)
==
0
)
...
@@ -643,10 +663,10 @@ exec_command(const char *cmd,
...
@@ -643,10 +663,10 @@ exec_command(const char *cmd,
if
(
!
options
[
0
])
if
(
!
options
[
0
])
{
{
if
(
pset
->
cur_cmd_interactive
)
if
(
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"
\\
%s: missing required argument"
,
cmd
);
fprintf
(
stderr
,
"
\\
%s: missing required argument"
,
cmd
);
else
else
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
->
progname
,
cmd
);
fprintf
(
stderr
,
"%s:
\\
%s: missing required argument"
,
pset
.
progname
,
cmd
);
success
=
false
;
success
=
false
;
}
}
else
else
...
@@ -698,19 +718,19 @@ exec_command(const char *cmd,
...
@@ -698,19 +718,19 @@ exec_command(const char *cmd,
/* \x -- toggle expanded table representation */
/* \x -- toggle expanded table representation */
else
if
(
strcmp
(
cmd
,
"x"
)
==
0
)
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) */
/* list table rights (grant/revoke) */
else
if
(
strcmp
(
cmd
,
"z"
)
==
0
)
else
if
(
strcmp
(
cmd
,
"z"
)
==
0
)
success
=
permissionsList
(
options
[
0
]
,
pset
);
success
=
permissionsList
(
options
[
0
]);
else
if
(
strcmp
(
cmd
,
"!"
)
==
0
)
else
if
(
strcmp
(
cmd
,
"!"
)
==
0
)
success
=
do_shell
(
options_string
);
success
=
do_shell
(
options_string
);
else
if
(
strcmp
(
cmd
,
"?"
)
==
0
)
else
if
(
strcmp
(
cmd
,
"?"
)
==
0
)
slashUsage
(
pset
);
slashUsage
();
#ifdef NOT_USED
#ifdef NOT_USED
...
@@ -748,7 +768,7 @@ exec_command(const char *cmd,
...
@@ -748,7 +768,7 @@ exec_command(const char *cmd,
* The return value is malloc()'ed.
* The return value is malloc()'ed.
*/
*/
static
char
*
static
char
*
unescape
(
const
char
*
source
,
PsqlSettings
*
pset
)
unescape
(
const
char
*
source
)
{
{
unsigned
char
*
p
;
unsigned
char
*
p
;
bool
esc
=
false
;
/* Last character we saw was the escape
bool
esc
=
false
;
/* Last character we saw was the escape
...
@@ -831,8 +851,9 @@ unescape(const char *source, PsqlSettings *pset)
...
@@ -831,8 +851,9 @@ unescape(const char *source, PsqlSettings *pset)
len
=
strcspn
(
p
+
2
,
"}"
);
len
=
strcspn
(
p
+
2
,
"}"
);
copy
=
xstrdup
(
p
+
2
);
copy
=
xstrdup
(
p
+
2
);
copy
[
len
]
=
'\0'
;
copy
[
len
]
=
'\0'
;
value
=
interpolate_var
(
copy
,
pset
);
value
=
GetVariable
(
pset
.
vars
,
copy
);
if
(
!
value
)
value
=
""
;
length
+=
strlen
(
value
)
-
(
len
+
3
);
length
+=
strlen
(
value
)
-
(
len
+
3
);
new
=
realloc
(
destination
,
length
);
new
=
realloc
(
destination
,
length
);
if
(
!
new
)
if
(
!
new
)
...
@@ -871,40 +892,42 @@ unescape(const char *source, PsqlSettings *pset)
...
@@ -871,40 +892,42 @@ unescape(const char *source, PsqlSettings *pset)
*
*
* Connects to a database (new_dbname) as a certain user (new_user).
* 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.
* 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.)
* dbname is handled by libpq.)
* Returns true if all ok, false if the new connection couldn't be established
* 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.
* but the old one was set back. Otherwise it terminates the program.
*/
*/
static
bool
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
*
dbparam
=
NULL
;
const
char
*
userparam
=
NULL
;
const
char
*
userparam
=
NULL
;
const
char
*
pwparam
=
NULL
;
const
char
*
pwparam
=
NULL
;
char
*
prompted_password
=
NULL
;
char
*
prompted_password
=
NULL
;
char
*
prompted_user
=
NULL
;
bool
need_pass
;
bool
need_pass
;
bool
success
=
false
;
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 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
);
dbparam
=
PQdb
(
oldconn
);
else
else
dbparam
=
new_dbname
;
dbparam
=
new_dbname
;
/* If user is ""
or "-"
then use the old one */
/* If user is "" 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
(
new_user
&&
PQuser
(
oldconn
)
&&
strcmp
(
new_user
,
""
)
==
0
)
userparam
=
PQuser
(
oldconn
);
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
else
userparam
=
new_user
;
userparam
=
new_user
;
/* need to prompt for password? */
/* need to prompt for password? */
if
(
pset
->
getPassword
)
if
(
pset
.
getPassword
)
pwparam
=
prompted_password
=
simple_prompt
(
"Password: "
,
100
,
false
);
/* need to save for
pwparam
=
prompted_password
=
simple_prompt
(
"Password: "
,
100
,
false
);
/* need to save for
* free() */
* free() */
...
@@ -912,7 +935,7 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
...
@@ -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
* Use old password if no new one given (if you didn't have an old
* one, fine)
* one, fine)
*/
*/
if
(
!
pwparam
)
if
(
!
pwparam
&&
oldconn
)
pwparam
=
PQpass
(
oldconn
);
pwparam
=
PQpass
(
oldconn
);
...
@@ -925,18 +948,18 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
...
@@ -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
* the default PGCLIENTENCODING value. -- 1998/12/12 Tatsuo Ishii
*/
*/
if
(
!
pset
->
has_client_encoding
)
if
(
!
pset
.
has_client_encoding
)
putenv
(
"PGCLIENTENCODING="
);
putenv
(
"PGCLIENTENCODING="
);
#endif
#endif
do
do
{
{
need_pass
=
false
;
need_pass
=
false
;
pset
->
db
=
PQsetdbLogin
(
PQhost
(
oldconn
),
PQport
(
oldconn
),
pset
.
db
=
PQsetdbLogin
(
PQhost
(
oldconn
),
PQport
(
oldconn
),
NULL
,
NULL
,
dbparam
,
userparam
,
pwparam
);
NULL
,
NULL
,
dbparam
,
userparam
,
pwparam
);
if
(
PQstatus
(
pset
->
db
)
==
CONNECTION_BAD
&&
if
(
PQstatus
(
pset
.
db
)
==
CONNECTION_BAD
&&
strcmp
(
PQerrorMessage
(
pset
->
db
),
"fe_sendauth: no password supplied
\n
"
)
==
0
)
strcmp
(
PQerrorMessage
(
pset
.
db
),
"fe_sendauth: no password supplied
\n
"
)
==
0
)
{
{
need_pass
=
true
;
need_pass
=
true
;
free
(
prompted_password
);
free
(
prompted_password
);
...
@@ -946,40 +969,39 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
...
@@ -946,40 +969,39 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
}
while
(
need_pass
);
}
while
(
need_pass
);
free
(
prompted_password
);
free
(
prompted_password
);
free
(
prompted_user
);
/*
/*
* If connection failed, try at least keep the old one. That's
* If connection failed, try at least keep the old one. That's
* probably more convenient than just kicking you out of the program.
* 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
));
fprintf
(
stderr
,
"
%s"
,
PQerrorMessage
(
pset
.
db
));
PQfinish
(
pset
->
db
);
PQfinish
(
pset
.
db
);
if
(
oldconn
)
if
(
oldconn
)
{
{
fputs
(
"Previous connection kept
\n
"
,
stderr
);
fputs
(
"Previous connection kept
\n
"
,
stderr
);
pset
->
db
=
oldconn
;
pset
.
db
=
oldconn
;
}
}
else
else
pset
->
db
=
NULL
;
pset
.
db
=
NULL
;
}
}
else
else
{
{
/* we don't want unpredictable things to
/* we don't want unpredictable things to
* happen in scripting mode */
* happen in scripting mode */
fprintf
(
stderr
,
"%s:
\\
connect: %s"
,
pset
->
progname
,
PQerrorMessage
(
pset
->
db
));
fprintf
(
stderr
,
"%s:
\\
connect: %s"
,
pset
.
progname
,
PQerrorMessage
(
pset
.
db
));
PQfinish
(
pset
->
db
);
PQfinish
(
pset
.
db
);
if
(
oldconn
)
if
(
oldconn
)
PQfinish
(
oldconn
);
PQfinish
(
oldconn
);
pset
->
db
=
NULL
;
pset
.
db
=
NULL
;
}
}
}
}
else
else
{
{
if
(
!
GetVariable
(
pset
->
vars
,
"quiet"
))
if
(
!
QUIET
(
))
{
{
if
(
userparam
!=
new_user
)
/* no new user */
if
(
userparam
!=
new_user
)
/* no new user */
printf
(
"You are now connected to database %s.
\n
"
,
dbparam
);
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)
...
@@ -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
);
printf
(
"You are now connected as new user %s.
\n
"
,
new_user
);
else
/* both new */
else
/* both new */
printf
(
"You are now connected to database %s as user %s.
\n
"
,
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
)
if
(
oldconn
)
...
@@ -996,6 +1018,12 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
...
@@ -996,6 +1018,12 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
success
=
true
;
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
;
return
success
;
}
}
...
@@ -1191,7 +1219,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
...
@@ -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.
* Handler for \i, but can be used for other things as well.
*/
*/
bool
bool
process_file
(
const
char
*
filename
,
PsqlSettings
*
pset
)
process_file
(
const
char
*
filename
)
{
{
FILE
*
fd
;
FILE
*
fd
;
int
result
;
int
result
;
...
@@ -1207,11 +1235,13 @@ process_file(const char *filename, PsqlSettings *pset)
...
@@ -1207,11 +1235,13 @@ process_file(const char *filename, PsqlSettings *pset)
if
(
!
fd
)
if
(
!
fd
)
{
{
if
(
!
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"%s: "
,
pset
.
progname
);
perror
(
filename
);
perror
(
filename
);
return
false
;
return
false
;
}
}
result
=
MainLoop
(
pset
,
fd
);
result
=
MainLoop
(
fd
);
fclose
(
fd
);
fclose
(
fd
);
return
(
result
==
EXIT_SUCCESS
);
return
(
result
==
EXIT_SUCCESS
);
}
}
...
...
src/bin/psql/command.h
View file @
7c9390ca
...
@@ -24,19 +24,18 @@ typedef enum _backslashResult
...
@@ -24,19 +24,18 @@ typedef enum _backslashResult
backslashResult
HandleSlashCmds
(
PsqlSettings
*
pset
,
backslashResult
const
char
*
line
,
HandleSlashCmds
(
const
char
*
line
,
PQExpBuffer
query_buf
,
PQExpBuffer
query_buf
,
const
char
**
end_of_cmd
);
const
char
**
end_of_cmd
);
bool
process_file
(
const
char
*
filename
,
bool
PsqlSettings
*
pset
);
process_file
(
const
char
*
filename
);
bool
bool
do_pset
(
const
char
*
param
,
do_pset
(
const
char
*
param
,
const
char
*
value
,
const
char
*
value
,
printQueryOpt
*
popt
,
printQueryOpt
*
popt
,
bool
quiet
);
bool
quiet
);
#endif
#endif
src/bin/psql/common.c
View file @
7c9390ca
#include <config.h>
#include <c.h>
#include <c.h>
#include "common.h"
#include "common.h"
#include <errno.h>
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
...
@@ -12,7 +12,6 @@
...
@@ -12,7 +12,6 @@
#include <strdup.h>
#include <strdup.h>
#endif
#endif
#include <signal.h>
#include <signal.h>
#include <assert.h>
#ifndef WIN32
#ifndef WIN32
#include <unistd.h>
/* for write() */
#include <unistd.h>
/* for write() */
#else
#else
...
@@ -73,64 +72,46 @@ xstrdup(const char *string)
...
@@ -73,64 +72,46 @@ xstrdup(const char *string)
* Upon failure, sets stdout and returns false.
* Upon failure, sets stdout and returns false.
*/
*/
bool
bool
setQFout
(
const
char
*
fname
,
PsqlSettings
*
pset
)
setQFout
(
const
char
*
fname
)
{
{
bool
status
=
true
;
bool
status
=
true
;
#ifdef USE_ASSERT_CHECKING
assert
(
pset
);
#else
if
(
!
pset
)
return
false
;
#endif
/* Close old file/pipe */
/* 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
)
if
(
pset
.
queryFoutPipe
)
pclose
(
pset
->
queryFout
);
pclose
(
pset
.
queryFout
);
else
else
fclose
(
pset
->
queryFout
);
fclose
(
pset
.
queryFout
);
}
}
/* If no filename, set stdout */
/* If no filename, set stdout */
if
(
!
fname
||
fname
[
0
]
==
'\0'
)
if
(
!
fname
||
fname
[
0
]
==
'\0'
)
{
{
pset
->
queryFout
=
stdout
;
pset
.
queryFout
=
stdout
;
pset
->
queryFoutPipe
=
false
;
pset
.
queryFoutPipe
=
false
;
}
}
else
if
(
*
fname
==
'|'
)
else
if
(
*
fname
==
'|'
)
{
{
const
char
*
pipename
=
fname
+
1
;
pset
.
queryFout
=
popen
(
fname
+
1
,
"w"
);
pset
.
queryFoutPipe
=
true
;
#ifndef __CYGWIN32__
pset
->
queryFout
=
popen
(
pipename
,
"w"
);
#else
pset
->
queryFout
=
popen
(
pipename
,
"wb"
);
#endif
pset
->
queryFoutPipe
=
true
;
}
}
else
else
{
{
#ifndef __CYGWIN32__
pset
.
queryFout
=
fopen
(
fname
,
"w"
);
pset
->
queryFout
=
fopen
(
fname
,
"w"
);
pset
.
queryFoutPipe
=
false
;
#else
pset
->
queryFout
=
fopen
(
fname
,
"wb"
);
#endif
pset
->
queryFoutPipe
=
false
;
}
}
if
(
!
pset
->
queryFout
)
if
(
!
(
pset
.
queryFout
)
)
{
{
perror
(
fname
);
fprintf
(
stderr
,
"%s: %s: %s
\n
"
,
pset
.
progname
,
fname
,
strerror
(
errno
)
);
pset
->
queryFout
=
stdout
;
pset
.
queryFout
=
stdout
;
pset
->
queryFoutPipe
=
false
;
pset
.
queryFoutPipe
=
false
;
status
=
false
;
status
=
false
;
}
}
/* Direct signals */
/* Direct signals */
if
(
pset
->
queryFoutPipe
)
if
(
pset
.
queryFoutPipe
)
pqsignal
(
SIGPIPE
,
SIG_IGN
);
pqsignal
(
SIGPIPE
,
SIG_IGN
);
else
else
pqsignal
(
SIGPIPE
,
SIG_DFL
);
pqsignal
(
SIGPIPE
,
SIG_DFL
);
...
@@ -211,93 +192,6 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
...
@@ -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
* Code to support query cancellation
*
*
...
@@ -333,21 +227,21 @@ handle_sigint(SIGNAL_ARGS)
...
@@ -333,21 +227,21 @@ handle_sigint(SIGNAL_ARGS)
* PSQLexec
* PSQLexec
*
*
* This is the way to send "backdoor" queries (those not directly entered
* 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
*
PGresult
*
PSQLexec
(
PsqlSettings
*
pset
,
const
char
*
query
)
PSQLexec
(
const
char
*
query
)
{
{
PGresult
*
res
;
PGresult
*
res
;
const
char
*
var
;
const
char
*
var
;
if
(
!
pset
->
db
)
if
(
!
pset
.
db
)
{
{
fputs
(
"You are currently not connected to a database.
\n
"
,
stderr
);
fputs
(
"You are currently not connected to a database.
\n
"
,
stderr
);
return
NULL
;
return
NULL
;
}
}
var
=
GetVariable
(
pset
->
vars
,
"echo_secret
"
);
var
=
GetVariable
(
pset
.
vars
,
"ECHO_HIDDEN
"
);
if
(
var
)
if
(
var
)
{
{
printf
(
"********* QUERY *********
\n
%s
\n
*************************
\n\n
"
,
query
);
printf
(
"********* QUERY *********
\n
%s
\n
*************************
\n\n
"
,
query
);
...
@@ -357,50 +251,50 @@ PSQLexec(PsqlSettings *pset, const char *query)
...
@@ -357,50 +251,50 @@ PSQLexec(PsqlSettings *pset, const char *query)
if
(
var
&&
strcmp
(
var
,
"noexec"
)
==
0
)
if
(
var
&&
strcmp
(
var
,
"noexec"
)
==
0
)
return
NULL
;
return
NULL
;
cancelConn
=
pset
->
db
;
cancelConn
=
pset
.
db
;
pqsignal
(
SIGINT
,
handle_sigint
);
/* control-C => cancel */
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 */
pqsignal
(
SIGINT
,
SIG_DFL
);
/* now control-C is back to normal */
if
(
PQstatus
(
pset
->
db
)
==
CONNECTION_OK
)
if
(
PQstatus
(
pset
.
db
)
==
CONNECTION_BAD
)
{
{
if
(
res
&&
(
PQresultStatus
(
res
)
==
PGRES_COMMAND_OK
||
if
(
!
pset
.
cur_cmd_interactive
)
PQresultStatus
(
res
)
==
PGRES_TUPLES_OK
||
{
PQresultStatus
(
res
)
==
PGRES_COPY_IN
||
fprintf
(
stderr
,
"%s: connection to server was lost"
,
pset
.
progname
);
PQresultStatus
(
res
)
==
PGRES_COPY_OUT
)
exit
(
EXIT_BADCONN
);
)
}
return
res
;
/* Normal success case... */
fputs
(
"The connection to the server was lost. Attempting reset: "
,
stderr
);
/* Normal failure case --- display error and return NULL */
PQreset
(
pset
.
db
);
fputs
(
PQerrorMessage
(
pset
->
db
),
pset
->
queryFout
);
if
(
PQstatus
(
pset
.
db
)
==
CONNECTION_BAD
)
PQclear
(
res
);
{
return
NULL
;
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
);
}
}
/* Lost connection. Report whatever libpq has to say,
if
(
res
&&
(
PQresultStatus
(
res
)
==
PGRES_COMMAND_OK
||
* then consider recovery.
PQresultStatus
(
res
)
==
PGRES_TUPLES_OK
||
*/
PQresultStatus
(
res
)
==
PGRES_COPY_IN
||
fputs
(
PQerrorMessage
(
pset
->
db
),
pset
->
queryFout
);
PQresultStatus
(
res
)
==
PGRES_COPY_OUT
)
PQclear
(
res
);
)
if
(
!
pset
->
cur_cmd_interactive
)
return
res
;
{
else
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
);
fputs
(
PQerrorMessage
(
pset
.
db
)
,
stderr
);
PQ
finish
(
pset
->
db
);
PQ
clear
(
res
);
pset
->
db
=
NULL
;
return
NULL
;
}
}
else
fputs
(
"Succeeded.
\n
"
,
stderr
);
return
NULL
;
}
}
...
@@ -418,19 +312,19 @@ PSQLexec(PsqlSettings *pset, const char *query)
...
@@ -418,19 +312,19 @@ PSQLexec(PsqlSettings *pset, const char *query)
* Returns true if the query executed successfully, false otherwise.
* Returns true if the query executed successfully, false otherwise.
*/
*/
bool
bool
SendQuery
(
PsqlSettings
*
pset
,
const
char
*
query
)
SendQuery
(
const
char
*
query
)
{
{
bool
success
=
false
;
bool
success
=
false
;
PGresult
*
results
;
PGresult
*
results
;
PGnotify
*
notify
;
PGnotify
*
notify
;
if
(
!
pset
->
db
)
if
(
!
pset
.
db
)
{
{
fputs
(
"You are currently not connected to a database.
\n
"
,
stderr
);
fputs
(
"You are currently not connected to a database.
\n
"
,
stderr
);
return
false
;
return
false
;
}
}
if
(
GetVariableBool
(
pset
->
vars
,
"singlestep
"
))
if
(
GetVariableBool
(
pset
.
vars
,
"SINGLESTEP
"
))
{
{
char
buf
[
3
];
char
buf
[
3
];
...
@@ -443,17 +337,23 @@ SendQuery(PsqlSettings *pset, const char *query)
...
@@ -443,17 +337,23 @@ SendQuery(PsqlSettings *pset, const char *query)
if
(
buf
[
0
]
==
'x'
)
if
(
buf
[
0
]
==
'x'
)
return
false
;
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
);
pqsignal
(
SIGINT
,
handle_sigint
);
results
=
PQexec
(
pset
->
db
,
query
);
results
=
PQexec
(
pset
.
db
,
query
);
pqsignal
(
SIGINT
,
SIG_DFL
);
pqsignal
(
SIGINT
,
SIG_DFL
);
if
(
results
==
NULL
)
if
(
results
==
NULL
)
{
{
fputs
(
PQerrorMessage
(
pset
->
db
),
pset
->
queryFout
);
fputs
(
PQerrorMessage
(
pset
.
db
),
pset
.
queryFout
);
success
=
false
;
success
=
false
;
}
}
else
else
...
@@ -461,24 +361,30 @@ SendQuery(PsqlSettings *pset, const char *query)
...
@@ -461,24 +361,30 @@ SendQuery(PsqlSettings *pset, const char *query)
switch
(
PQresultStatus
(
results
))
switch
(
PQresultStatus
(
results
))
{
{
case
PGRES_TUPLES_OK
:
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
;
/* open file/pipe */
if
(
!
setQFout
(
pset
->
gfname
,
&
settings_copy
))
if
(
!
setQFout
(
pset
.
gfname
))
{
{
success
=
false
;
success
=
false
;
break
;
break
;
}
}
printQuery
(
results
,
&
settings_copy
.
popt
,
settings_copy
.
queryFout
);
printQuery
(
results
,
&
pset
.
popt
,
pset
.
queryFout
);
/* close file/pipe */
/* close file/pipe */
setQFout
(
NULL
,
&
settings_copy
);
setQFout
(
NULL
);
free
(
pset
->
gfname
);
free
(
pset
.
gfname
);
pset
->
gfname
=
NULL
;
pset
.
gfname
=
NULL
;
pset
.
queryFout
=
queryFout_copy
;
pset
.
queryFoutPipe
=
queryFoutPipe_copy
;
success
=
true
;
success
=
true
;
break
;
break
;
...
@@ -486,77 +392,83 @@ SendQuery(PsqlSettings *pset, const char *query)
...
@@ -486,77 +392,83 @@ SendQuery(PsqlSettings *pset, const char *query)
else
else
{
{
success
=
true
;
success
=
true
;
printQuery
(
results
,
&
pset
->
popt
,
pset
->
queryFout
);
printQuery
(
results
,
&
pset
.
popt
,
pset
.
queryFout
);
}
}
break
;
break
;
case
PGRES_EMPTY_QUERY
:
case
PGRES_EMPTY_QUERY
:
success
=
true
;
success
=
true
;
break
;
break
;
case
PGRES_COMMAND_OK
:
case
PGRES_COMMAND_OK
:
{
char
buf
[
10
];
success
=
true
;
success
=
true
;
pset
->
lastOid
=
PQoidValue
(
results
);
sprintf
(
buf
,
"%u"
,
(
unsigned
int
)
PQoidValue
(
results
));
if
(
!
GetVariableBool
(
pset
->
vars
,
"quiet"
))
if
(
!
QUIET
())
fprintf
(
pset
->
queryFout
,
"%s
\n
"
,
PQcmdStatus
(
results
));
fprintf
(
pset
.
queryFout
,
"%s
\n
"
,
PQcmdStatus
(
results
));
SetVariable
(
pset
.
vars
,
"LASTOID"
,
buf
);
break
;
break
;
}
case
PGRES_COPY_OUT
:
case
PGRES_COPY_OUT
:
success
=
handleCopyOut
(
pset
->
db
,
pset
->
queryFout
);
success
=
handleCopyOut
(
pset
.
db
,
pset
.
queryFout
);
break
;
break
;
case
PGRES_COPY_IN
:
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
"
puts
(
"Enter data to be copied followed by a newline.
\n
"
"End with a backslash and a period on a line by itself."
);
"End with a backslash and a period on a line by itself."
);
success
=
handleCopyIn
(
pset
->
db
,
pset
->
cur_cmd_source
,
success
=
handleCopyIn
(
pset
.
db
,
pset
.
cur_cmd_source
,
pset
->
cur_cmd_interactive
?
get_prompt
(
pset
,
PROMPT_COPY
)
:
NULL
);
pset
.
cur_cmd_interactive
?
get_prompt
(
PROMPT_COPY
)
:
NULL
);
break
;
break
;
case
PGRES_NONFATAL_ERROR
:
case
PGRES_NONFATAL_ERROR
:
case
PGRES_FATAL_ERROR
:
case
PGRES_FATAL_ERROR
:
case
PGRES_BAD_RESPONSE
:
case
PGRES_BAD_RESPONSE
:
success
=
false
;
success
=
false
;
fputs
(
PQerrorMessage
(
pset
->
db
),
stderr
);
fputs
(
PQerrorMessage
(
pset
.
db
),
stderr
);
break
;
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
"
,
fprintf
(
stderr
,
"%s: connection to server was lost"
,
pset
.
progname
);
pset
->
progname
);
exit
(
EXIT_BADCONN
);
exit
(
EXIT_BADCONN
);
}
}
fputs
(
"The connection to the server was lost. Attempting reset: "
,
stderr
);
fputs
(
"The connection to the server was lost. Attempting reset: "
,
stderr
);
fflush
(
stderr
);
PQreset
(
pset
.
db
);
PQreset
(
pset
->
db
);
if
(
PQstatus
(
pset
.
db
)
==
CONNECTION_BAD
)
if
(
PQstatus
(
pset
->
db
)
==
CONNECTION_BAD
)
{
{
fputs
(
"Failed.
\n
"
,
stderr
);
fputs
(
"Failed.
\n
"
,
stderr
);
PQfinish
(
pset
->
db
);
PQfinish
(
pset
.
db
);
pset
->
db
=
NULL
;
PQclear
(
results
);
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
;
return
false
;
}
}
else
else
fputs
(
"Succeeded.
\n
"
,
stderr
);
fputs
(
"Succeeded.
\n
"
,
stderr
);
}
}
/* check for asynchronous notification returns */
/* 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
);
notify
->
relname
,
notify
->
be_pid
);
free
(
notify
);
free
(
notify
);
fflush
(
pset
->
queryFout
);
fflush
(
pset
.
queryFout
);
}
}
if
(
results
)
if
(
results
)
PQclear
(
results
);
PQclear
(
results
);
}
}
return
success
;
return
success
;
}
}
src/bin/psql/common.h
View file @
7c9390ca
...
@@ -8,18 +8,15 @@ char *
...
@@ -8,18 +8,15 @@ char *
xstrdup
(
const
char
*
string
);
xstrdup
(
const
char
*
string
);
bool
bool
setQFout
(
const
char
*
fname
,
PsqlSettings
*
pset
);
setQFout
(
const
char
*
fname
);
char
*
char
*
simple_prompt
(
const
char
*
prompt
,
int
maxlen
,
bool
echo
);
simple_prompt
(
const
char
*
prompt
,
int
maxlen
,
bool
echo
);
const
char
*
interpolate_var
(
const
char
*
name
,
PsqlSettings
*
pset
);
PGresult
*
PGresult
*
PSQLexec
(
PsqlSettings
*
pset
,
const
char
*
query
);
PSQLexec
(
const
char
*
query
);
bool
bool
SendQuery
(
PsqlSettings
*
pset
,
const
char
*
query
);
SendQuery
(
const
char
*
query
);
#endif
/* COMMON_H */
#endif
/* COMMON_H */
src/bin/psql/copy.c
View file @
7c9390ca
#include <config.h>
#include <c.h>
#include <c.h>
#include "copy.h"
#include "copy.h"
...
@@ -36,7 +35,7 @@
...
@@ -36,7 +35,7 @@
struct
copy_options
struct
copy_options
{
{
char
*
table
;
char
*
table
;
char
*
file
;
char
*
file
;
/* NULL = stdin/stdout */
bool
from
;
bool
from
;
bool
binary
;
bool
binary
;
bool
oids
;
bool
oids
;
...
@@ -59,7 +58,7 @@ free_copy_options(struct copy_options * ptr)
...
@@ -59,7 +58,7 @@ free_copy_options(struct copy_options * ptr)
static
struct
copy_options
*
static
struct
copy_options
*
parse_slash_copy
(
const
char
*
args
,
PsqlSettings
*
pset
)
parse_slash_copy
(
const
char
*
args
)
{
{
struct
copy_options
*
result
;
struct
copy_options
*
result
;
char
*
line
;
char
*
line
;
...
@@ -132,17 +131,15 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
...
@@ -132,17 +131,15 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
if
(
!
error
)
if
(
!
error
)
{
{
token
=
strtokx
(
NULL
,
"
\t
"
,
"'"
,
'\\'
,
NULL
,
NULL
);
token
=
strtokx
(
NULL
,
"
\t
"
,
"'"
,
'\\'
,
&
quote
,
NULL
);
if
(
!
token
)
if
(
!
token
)
error
=
true
;
error
=
true
;
else
else
if
(
!
quote
&&
(
strcasecmp
(
token
,
"stdin"
)
==
0
||
strcasecmp
(
token
,
"stdout"
)
==
0
))
result
->
file
=
NULL
;
else
result
->
file
=
xstrdup
(
token
);
result
->
file
=
xstrdup
(
token
);
}
}
#ifdef USE_ASSERT_CHECKING
assert
(
error
||
result
->
file
);
#endif
if
(
!
error
)
if
(
!
error
)
{
{
token
=
strtokx
(
NULL
,
"
\t
"
,
NULL
,
'\\'
,
NULL
,
NULL
);
token
=
strtokx
(
NULL
,
"
\t
"
,
NULL
,
'\\'
,
NULL
,
NULL
);
...
@@ -194,8 +191,8 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
...
@@ -194,8 +191,8 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
if
(
error
)
if
(
error
)
{
{
if
(
!
pset
->
cur_cmd_interactive
)
if
(
!
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"%s: "
,
pset
->
progname
);
fprintf
(
stderr
,
"%s: "
,
pset
.
progname
);
fputs
(
"
\\
copy: parse error at "
,
stderr
);
fputs
(
"
\\
copy: parse error at "
,
stderr
);
if
(
!
token
)
if
(
!
token
)
fputs
(
"end of line"
,
stderr
);
fputs
(
"end of line"
,
stderr
);
...
@@ -217,7 +214,7 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
...
@@ -217,7 +214,7 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
* file or route its response into the file.
* file or route its response into the file.
*/
*/
bool
bool
do_copy
(
const
char
*
args
,
PsqlSettings
*
pset
)
do_copy
(
const
char
*
args
)
{
{
char
query
[
128
+
NAMEDATALEN
];
char
query
[
128
+
NAMEDATALEN
];
FILE
*
copystream
;
FILE
*
copystream
;
...
@@ -226,7 +223,7 @@ do_copy(const char *args, PsqlSettings *pset)
...
@@ -226,7 +223,7 @@ do_copy(const char *args, PsqlSettings *pset)
bool
success
;
bool
success
;
/* parse options */
/* parse options */
options
=
parse_slash_copy
(
args
,
pset
);
options
=
parse_slash_copy
(
args
);
if
(
!
options
)
if
(
!
options
)
return
false
;
return
false
;
...
@@ -242,9 +239,9 @@ do_copy(const char *args, PsqlSettings *pset)
...
@@ -242,9 +239,9 @@ do_copy(const char *args, PsqlSettings *pset)
strcat
(
query
,
"WITH OIDS "
);
strcat
(
query
,
"WITH OIDS "
);
if
(
options
->
from
)
if
(
options
->
from
)
strcat
(
query
,
"FROM
stdin
"
);
strcat
(
query
,
"FROM
STDIN
"
);
else
else
strcat
(
query
,
"TO
stdout
"
);
strcat
(
query
,
"TO
STDOUT
"
);
if
(
options
->
delim
)
if
(
options
->
delim
)
...
@@ -254,24 +251,32 @@ do_copy(const char *args, PsqlSettings *pset)
...
@@ -254,24 +251,32 @@ do_copy(const char *args, PsqlSettings *pset)
strcat
(
query
,
"'"
);
strcat
(
query
,
"'"
);
}
}
if
(
options
->
null
)
{
strcat
(
query
,
" WITH NULL AS '"
);
strcat
(
query
,
options
->
null
);
strcat
(
query
,
"'"
);
}
if
(
options
->
from
)
if
(
options
->
from
)
#ifndef __CYGWIN32__
{
copystream
=
fopen
(
options
->
file
,
"r"
);
if
(
options
->
file
)
#else
copystream
=
fopen
(
options
->
file
,
"r"
);
copystream
=
fopen
(
options
->
file
,
"rb"
);
else
#endif
copystream
=
stdin
;
}
else
else
#ifndef __CYGWIN32__
{
copystream
=
fopen
(
options
->
file
,
"w"
);
if
(
options
->
file
)
#else
copystream
=
fopen
(
options
->
file
,
"w"
);
copystream
=
fopen
(
options
->
file
,
"wb"
);
else
#endif
copystream
=
stdout
;
}
if
(
!
copystream
)
if
(
!
copystream
)
{
{
if
(
!
pset
->
cur_cmd_interactive
)
if
(
!
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"%s: "
,
pset
->
progname
);
fprintf
(
stderr
,
"%s: "
,
pset
.
progname
);
fprintf
(
stderr
,
fprintf
(
stderr
,
"unable to open file %s: %s
\n
"
,
"unable to open file %s: %s
\n
"
,
options
->
file
,
strerror
(
errno
));
options
->
file
,
strerror
(
errno
));
...
@@ -279,40 +284,40 @@ do_copy(const char *args, PsqlSettings *pset)
...
@@ -279,40 +284,40 @@ do_copy(const char *args, PsqlSettings *pset)
return
false
;
return
false
;
}
}
result
=
PSQLexec
(
pset
,
query
);
result
=
PSQLexec
(
query
);
switch
(
PQresultStatus
(
result
))
switch
(
PQresultStatus
(
result
))
{
{
case
PGRES_COPY_OUT
:
case
PGRES_COPY_OUT
:
success
=
handleCopyOut
(
pset
->
db
,
copystream
);
success
=
handleCopyOut
(
pset
.
db
,
copystream
);
break
;
break
;
case
PGRES_COPY_IN
:
case
PGRES_COPY_IN
:
success
=
handleCopyIn
(
pset
->
db
,
copystream
,
NULL
);
success
=
handleCopyIn
(
pset
.
db
,
copystream
,
NULL
);
break
;
break
;
case
PGRES_NONFATAL_ERROR
:
case
PGRES_NONFATAL_ERROR
:
case
PGRES_FATAL_ERROR
:
case
PGRES_FATAL_ERROR
:
case
PGRES_BAD_RESPONSE
:
case
PGRES_BAD_RESPONSE
:
success
=
false
;
success
=
false
;
fputs
(
PQerrorMessage
(
pset
->
db
),
stderr
);
fputs
(
PQerrorMessage
(
pset
.
db
),
stderr
);
break
;
break
;
default:
default:
success
=
false
;
success
=
false
;
if
(
!
pset
->
cur_cmd_interactive
)
if
(
!
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"%s: "
,
pset
->
progname
);
fprintf
(
stderr
,
"%s: "
,
pset
.
progname
);
fprintf
(
stderr
,
"
\\
copy: unexpected response (%d)
\n
"
,
PQresultStatus
(
result
));
fprintf
(
stderr
,
"
\\
copy: unexpected response (%d)
\n
"
,
PQresultStatus
(
result
));
}
}
PQclear
(
result
);
PQclear
(
result
);
if
(
!
GetVariable
(
pset
->
vars
,
"quiet"
)
)
if
(
!
success
)
{
{
if
(
success
)
if
(
!
pset
.
cur_cmd_interactive
)
puts
(
"Successfully copied"
);
fprintf
(
stderr
,
"%s: "
,
pset
.
progname
);
else
fprintf
(
stderr
,
"
\\
copy failed
\n
"
);
puts
(
"Copy failed"
);
}
}
fclose
(
copystream
);
if
(
copystream
!=
stdout
&&
copystream
!=
stdin
)
fclose
(
copystream
);
free_copy_options
(
options
);
free_copy_options
(
options
);
return
success
;
return
success
;
}
}
...
@@ -396,7 +401,7 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
...
@@ -396,7 +401,7 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
while
(
!
copydone
)
while
(
!
copydone
)
{
/* for each input line ... */
{
/* for each input line ... */
if
(
prompt
&&
isatty
(
fileno
(
stdin
)))
if
(
prompt
&&
isatty
(
fileno
(
copystream
)))
{
{
fputs
(
prompt
,
stdout
);
fputs
(
prompt
,
stdout
);
fflush
(
stdout
);
fflush
(
stdout
);
...
...
src/bin/psql/copy.h
View file @
7c9390ca
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
/* handler for \copy */
/* handler for \copy */
bool
bool
do_copy
(
const
char
*
args
,
PsqlSettings
*
pset
);
do_copy
(
const
char
*
args
);
/* lower level processors for copy in/out streams */
/* lower level processors for copy in/out streams */
...
...
src/bin/psql/describe.c
View file @
7c9390ca
...
@@ -31,11 +31,11 @@
...
@@ -31,11 +31,11 @@
* takes an optional regexp to match specific aggregates by name
* takes an optional regexp to match specific aggregates by name
*/
*/
bool
bool
describeAggregates
(
const
char
*
name
,
PsqlSettings
*
pset
)
describeAggregates
(
const
char
*
name
)
{
{
char
buf
[
384
+
2
*
REGEXP_CUTOFF
];
char
buf
[
384
+
2
*
REGEXP_CUTOFF
];
PGresult
*
res
;
PGresult
*
res
;
printQueryOpt
myopt
=
pset
->
popt
;
printQueryOpt
myopt
=
pset
.
popt
;
/*
/*
* There are two kinds of aggregates: ones that work on particular
* There are two kinds of aggregates: ones that work on particular
...
@@ -72,14 +72,14 @@ describeAggregates(const char *name, PsqlSettings *pset)
...
@@ -72,14 +72,14 @@ describeAggregates(const char *name, PsqlSettings *pset)
strcat
(
buf
,
"ORDER BY
\"
Name
\"
,
\"
Type
\"
"
);
strcat
(
buf
,
"ORDER BY
\"
Name
\"
,
\"
Type
\"
"
);
res
=
PSQLexec
(
pset
,
buf
);
res
=
PSQLexec
(
buf
);
if
(
!
res
)
if
(
!
res
)
return
false
;
return
false
;
myopt
.
nullPrint
=
NULL
;
myopt
.
nullPrint
=
NULL
;
myopt
.
title
=
"List of aggregates"
;
myopt
.
title
=
"List of aggregates"
;
printQuery
(
res
,
&
myopt
,
pset
->
queryFout
);
printQuery
(
res
,
&
myopt
,
pset
.
queryFout
);
PQclear
(
res
);
PQclear
(
res
);
return
true
;
return
true
;
...
@@ -90,11 +90,11 @@ describeAggregates(const char *name, PsqlSettings *pset)
...
@@ -90,11 +90,11 @@ describeAggregates(const char *name, PsqlSettings *pset)
* Takes an optional regexp to narrow down the function name
* Takes an optional regexp to narrow down the function name
*/
*/
bool
bool
describeFunctions
(
const
char
*
name
,
PsqlSettings
*
pset
,
bool
verbose
)
describeFunctions
(
const
char
*
name
,
bool
verbose
)
{
{
char
buf
[
384
+
REGEXP_CUTOFF
];
char
buf
[
384
+
REGEXP_CUTOFF
];
PGresult
*
res
;
PGresult
*
res
;
printQueryOpt
myopt
=
pset
->
popt
;
printQueryOpt
myopt
=
pset
.
popt
;
/*
/*
* we skip in/out funcs by excluding functions that take some
* we skip in/out funcs by excluding functions that take some
...
@@ -125,14 +125,14 @@ describeFunctions(const char *name, PsqlSettings *pset, bool verbose)
...
@@ -125,14 +125,14 @@ describeFunctions(const char *name, PsqlSettings *pset, bool verbose)
}
}
strcat
(
buf
,
"ORDER BY
\"
Function
\"
,
\"
Result
\"
,
\"
Arguments
\"
"
);
strcat
(
buf
,
"ORDER BY
\"
Function
\"
,
\"
Result
\"
,
\"
Arguments
\"
"
);
res
=
PSQLexec
(
pset
,
buf
);
res
=
PSQLexec
(
buf
);
if
(
!
res
)
if
(
!
res
)
return
false
;
return
false
;
myopt
.
nullPrint
=
NULL
;
myopt
.
nullPrint
=
NULL
;
myopt
.
title
=
"List of functions"
;
myopt
.
title
=
"List of functions"
;
printQuery
(
res
,
&
myopt
,
pset
->
queryFout
);
printQuery
(
res
,
&
myopt
,
pset
.
queryFout
);
PQclear
(
res
);
PQclear
(
res
);
return
true
;
return
true
;
...
@@ -145,11 +145,11 @@ describeFunctions(const char *name, PsqlSettings *pset, bool verbose)
...
@@ -145,11 +145,11 @@ describeFunctions(const char *name, PsqlSettings *pset, bool verbose)
* describe types
* describe types
*/
*/
bool
bool
describeTypes
(
const
char
*
name
,
PsqlSettings
*
pset
,
bool
verbose
)
describeTypes
(
const
char
*
name
,
bool
verbose
)
{
{
char
buf
[
256
+
REGEXP_CUTOFF
];
char
buf
[
256
+
REGEXP_CUTOFF
];
PGresult
*
res
;
PGresult
*
res
;
printQueryOpt
myopt
=
pset
->
popt
;
printQueryOpt
myopt
=
pset
.
popt
;
strcpy
(
buf
,
"SELECT t.typname AS
\"
Type
\"
"
);
strcpy
(
buf
,
"SELECT t.typname AS
\"
Type
\"
"
);
if
(
verbose
)
if
(
verbose
)
...
@@ -169,14 +169,14 @@ describeTypes(const char *name, PsqlSettings *pset, bool verbose)
...
@@ -169,14 +169,14 @@ describeTypes(const char *name, PsqlSettings *pset, bool verbose)
}
}
strcat
(
buf
,
"ORDER BY t.typname;"
);
strcat
(
buf
,
"ORDER BY t.typname;"
);
res
=
PSQLexec
(
pset
,
buf
);
res
=
PSQLexec
(
buf
);
if
(
!
res
)
if
(
!
res
)
return
false
;
return
false
;
myopt
.
nullPrint
=
NULL
;
myopt
.
nullPrint
=
NULL
;
myopt
.
title
=
"List of types"
;
myopt
.
title
=
"List of types"
;
printQuery
(
res
,
&
myopt
,
pset
->
queryFout
);
printQuery
(
res
,
&
myopt
,
pset
.
queryFout
);
PQclear
(
res
);
PQclear
(
res
);
return
true
;
return
true
;
...
@@ -187,11 +187,11 @@ describeTypes(const char *name, PsqlSettings *pset, bool verbose)
...
@@ -187,11 +187,11 @@ describeTypes(const char *name, PsqlSettings *pset, bool verbose)
/* \do
/* \do
*/
*/
bool
bool
describeOperators
(
const
char
*
name
,
PsqlSettings
*
pset
)
describeOperators
(
const
char
*
name
)
{
{
char
buf
[
1536
+
3
*
REGEXP_CUTOFF
];
char
buf
[
1536
+
3
*
REGEXP_CUTOFF
];
PGresult
*
res
;
PGresult
*
res
;
printQueryOpt
myopt
=
pset
->
popt
;
printQueryOpt
myopt
=
pset
.
popt
;
strcpy
(
buf
,
strcpy
(
buf
,
"SELECT o.oprname AS
\"
Op
\"
,
\n
"
"SELECT o.oprname AS
\"
Op
\"
,
\n
"
...
@@ -251,14 +251,14 @@ describeOperators(const char *name, PsqlSettings *pset)
...
@@ -251,14 +251,14 @@ describeOperators(const char *name, PsqlSettings *pset)
}
}
strcat
(
buf
,
"
\n
ORDER BY
\"
Op
\"
,
\"
Left arg
\"
,
\"
Right arg
\"
,
\"
Result
\"
"
);
strcat
(
buf
,
"
\n
ORDER BY
\"
Op
\"
,
\"
Left arg
\"
,
\"
Right arg
\"
,
\"
Result
\"
"
);
res
=
PSQLexec
(
pset
,
buf
);
res
=
PSQLexec
(
buf
);
if
(
!
res
)
if
(
!
res
)
return
false
;
return
false
;
myopt
.
nullPrint
=
NULL
;
myopt
.
nullPrint
=
NULL
;
myopt
.
title
=
"List of operators"
;
myopt
.
title
=
"List of operators"
;
printQuery
(
res
,
&
myopt
,
pset
->
queryFout
);
printQuery
(
res
,
&
myopt
,
pset
.
queryFout
);
PQclear
(
res
);
PQclear
(
res
);
return
true
;
return
true
;
...
@@ -271,11 +271,11 @@ describeOperators(const char *name, PsqlSettings *pset)
...
@@ -271,11 +271,11 @@ describeOperators(const char *name, PsqlSettings *pset)
* for \l, \list, and -l switch
* for \l, \list, and -l switch
*/
*/
bool
bool
listAllDbs
(
PsqlSettings
*
pset
,
bool
desc
)
listAllDbs
(
bool
desc
)
{
{
PGresult
*
res
;
PGresult
*
res
;
char
buf
[
512
];
char
buf
[
512
];
printQueryOpt
myopt
=
pset
->
popt
;
printQueryOpt
myopt
=
pset
.
popt
;
strcpy
(
buf
,
strcpy
(
buf
,
"SELECT pg_database.datname as
\"
Database
\"
,
\n
"
"SELECT pg_database.datname as
\"
Database
\"
,
\n
"
...
@@ -306,14 +306,14 @@ listAllDbs(PsqlSettings *pset, bool desc)
...
@@ -306,14 +306,14 @@ listAllDbs(PsqlSettings *pset, bool desc)
strcat
(
buf
,
"ORDER BY
\"
Database
\"
"
);
strcat
(
buf
,
"ORDER BY
\"
Database
\"
"
);
res
=
PSQLexec
(
pset
,
buf
);
res
=
PSQLexec
(
buf
);
if
(
!
res
)
if
(
!
res
)
return
false
;
return
false
;
myopt
.
nullPrint
=
NULL
;
myopt
.
nullPrint
=
NULL
;
myopt
.
title
=
"List of databases"
;
myopt
.
title
=
"List of databases"
;
printQuery
(
res
,
&
myopt
,
pset
->
queryFout
);
printQuery
(
res
,
&
myopt
,
pset
.
queryFout
);
PQclear
(
res
);
PQclear
(
res
);
return
true
;
return
true
;
...
@@ -325,11 +325,11 @@ listAllDbs(PsqlSettings *pset, bool desc)
...
@@ -325,11 +325,11 @@ listAllDbs(PsqlSettings *pset, bool desc)
*
*
*/
*/
bool
bool
permissionsList
(
const
char
*
name
,
PsqlSettings
*
pset
)
permissionsList
(
const
char
*
name
)
{
{
char
descbuf
[
256
+
REGEXP_CUTOFF
];
char
descbuf
[
256
+
REGEXP_CUTOFF
];
PGresult
*
res
;
PGresult
*
res
;
printQueryOpt
myopt
=
pset
->
popt
;
printQueryOpt
myopt
=
pset
.
popt
;
descbuf
[
0
]
=
'\0'
;
descbuf
[
0
]
=
'\0'
;
/* Currently, we ignore indexes since they have no meaningful rights */
/* Currently, we ignore indexes since they have no meaningful rights */
...
@@ -346,15 +346,15 @@ permissionsList(const char *name, PsqlSettings *pset)
...
@@ -346,15 +346,15 @@ permissionsList(const char *name, PsqlSettings *pset)
}
}
strcat
(
descbuf
,
"ORDER BY relname"
);
strcat
(
descbuf
,
"ORDER BY relname"
);
res
=
PSQLexec
(
pset
,
descbuf
);
res
=
PSQLexec
(
descbuf
);
if
(
!
res
)
if
(
!
res
)
return
false
;
return
false
;
myopt
.
nullPrint
=
NULL
;
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
;
myopt
.
title
=
descbuf
;
printQuery
(
res
,
&
myopt
,
pset
->
queryFout
);
printQuery
(
res
,
&
myopt
,
pset
.
queryFout
);
PQclear
(
res
);
PQclear
(
res
);
return
true
;
return
true
;
...
@@ -371,11 +371,11 @@ permissionsList(const char *name, PsqlSettings *pset)
...
@@ -371,11 +371,11 @@ permissionsList(const char *name, PsqlSettings *pset)
* lists of things, there are other \d? commands.
* lists of things, there are other \d? commands.
*/
*/
bool
bool
objectDescription
(
const
char
*
object
,
PsqlSettings
*
pset
)
objectDescription
(
const
char
*
object
)
{
{
char
descbuf
[
2048
+
7
*
REGEXP_CUTOFF
];
char
descbuf
[
2048
+
7
*
REGEXP_CUTOFF
];
PGresult
*
res
;
PGresult
*
res
;
printQueryOpt
myopt
=
pset
->
popt
;
printQueryOpt
myopt
=
pset
.
popt
;
descbuf
[
0
]
=
'\0'
;
descbuf
[
0
]
=
'\0'
;
...
@@ -466,7 +466,7 @@ objectDescription(const char *object, PsqlSettings *pset)
...
@@ -466,7 +466,7 @@ objectDescription(const char *object, PsqlSettings *pset)
strcat
(
descbuf
,
"
\n
ORDER BY
\"
Name
\"
"
);
strcat
(
descbuf
,
"
\n
ORDER BY
\"
Name
\"
"
);
res
=
PSQLexec
(
pset
,
descbuf
);
res
=
PSQLexec
(
descbuf
);
if
(
!
res
)
if
(
!
res
)
return
false
;
return
false
;
...
@@ -474,7 +474,7 @@ objectDescription(const char *object, PsqlSettings *pset)
...
@@ -474,7 +474,7 @@ objectDescription(const char *object, PsqlSettings *pset)
myopt
.
nullPrint
=
NULL
;
myopt
.
nullPrint
=
NULL
;
myopt
.
title
=
"Object descriptions"
;
myopt
.
title
=
"Object descriptions"
;
printQuery
(
res
,
&
myopt
,
pset
->
queryFout
);
printQuery
(
res
,
&
myopt
,
pset
.
queryFout
);
PQclear
(
res
);
PQclear
(
res
);
return
true
;
return
true
;
...
@@ -507,11 +507,11 @@ xmalloc(size_t size)
...
@@ -507,11 +507,11 @@ xmalloc(size_t size)
bool
bool
describeTableDetails
(
const
char
*
name
,
PsqlSettings
*
pset
,
bool
desc
)
describeTableDetails
(
const
char
*
name
,
bool
desc
)
{
{
char
buf
[
512
+
INDEX_MAX_KEYS
*
NAMEDATALEN
];
char
buf
[
512
+
INDEX_MAX_KEYS
*
NAMEDATALEN
];
PGresult
*
res
=
NULL
;
PGresult
*
res
=
NULL
;
printTableOpt
myopt
=
pset
->
popt
.
topt
;
printTableOpt
myopt
=
pset
.
popt
.
topt
;
int
i
;
int
i
;
const
char
*
view_def
=
NULL
;
const
char
*
view_def
=
NULL
;
const
char
*
headers
[
5
];
const
char
*
headers
[
5
];
...
@@ -536,14 +536,14 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
...
@@ -536,14 +536,14 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
"SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules
\n
"
"SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules
\n
"
"FROM pg_class WHERE relname='%s'"
,
"FROM pg_class WHERE relname='%s'"
,
name
);
name
);
res
=
PSQLexec
(
pset
,
buf
);
res
=
PSQLexec
(
buf
);
if
(
!
res
)
if
(
!
res
)
return
false
;
return
false
;
/* Did we get anything? */
/* Did we get anything? */
if
(
PQntuples
(
res
)
==
0
)
if
(
PQntuples
(
res
)
==
0
)
{
{
if
(
!
GetVariableBool
(
pset
->
vars
,
"quiet"
))
if
(
!
QUIET
(
))
fprintf
(
stderr
,
"Did not find any relation named
\"
%s
\"
.
\n
"
,
name
);
fprintf
(
stderr
,
"Did not find any relation named
\"
%s
\"
.
\n
"
,
name
);
PQclear
(
res
);
PQclear
(
res
);
return
false
;
return
false
;
...
@@ -587,7 +587,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
...
@@ -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
"
strcat
(
buf
,
"'
\n
AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid
\n
"
"ORDER BY a.attnum"
);
"ORDER BY a.attnum"
);
res
=
PSQLexec
(
pset
,
buf
);
res
=
PSQLexec
(
buf
);
if
(
!
res
)
if
(
!
res
)
return
false
;
return
false
;
...
@@ -595,7 +595,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
...
@@ -595,7 +595,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
if
(
tableinfo
.
hasrules
)
{
if
(
tableinfo
.
hasrules
)
{
PGresult
*
result
;
PGresult
*
result
;
sprintf
(
buf
,
"SELECT definition FROM pg_views WHERE viewname = '%s'"
,
name
);
sprintf
(
buf
,
"SELECT definition FROM pg_views WHERE viewname = '%s'"
,
name
);
result
=
PSQLexec
(
pset
,
buf
);
result
=
PSQLexec
(
buf
);
if
(
!
result
)
if
(
!
result
)
{
{
PQclear
(
res
);
PQclear
(
res
);
...
@@ -655,7 +655,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
...
@@ -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"
,
"WHERE c.relname = '%s' AND c.oid = d.adrelid AND d.adnum = %s"
,
name
,
PQgetvalue
(
res
,
i
,
6
));
name
,
PQgetvalue
(
res
,
i
,
6
));
result
=
PSQLexec
(
pset
,
buf
);
result
=
PSQLexec
(
buf
);
if
(
!
result
)
if
(
!
result
)
error
=
true
;
error
=
true
;
else
else
...
@@ -710,7 +710,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
...
@@ -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"
,
"WHERE i.indexrelid = c.oid AND c.relname = '%s' AND c.relam = a.oid"
,
name
);
name
);
result
=
PSQLexec
(
pset
,
buf
);
result
=
PSQLexec
(
buf
);
if
(
!
result
)
if
(
!
result
)
error
=
true
;
error
=
true
;
else
else
...
@@ -750,7 +750,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
...
@@ -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
"
"WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid
\n
"
"ORDER BY c2.relname"
,
"ORDER BY c2.relname"
,
name
);
name
);
result1
=
PSQLexec
(
pset
,
buf
);
result1
=
PSQLexec
(
buf
);
if
(
!
result1
)
if
(
!
result1
)
error
=
true
;
error
=
true
;
else
else
...
@@ -764,7 +764,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
...
@@ -764,7 +764,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
"FROM pg_relcheck r, pg_class c
\n
"
"FROM pg_relcheck r, pg_class c
\n
"
"WHERE c.relname='%s' AND c.oid = r.rcrelid"
,
"WHERE c.relname='%s' AND c.oid = r.rcrelid"
,
name
);
name
);
result2
=
PSQLexec
(
pset
,
buf
);
result2
=
PSQLexec
(
buf
);
if
(
!
result2
)
if
(
!
result2
)
error
=
true
;
error
=
true
;
else
else
...
@@ -779,7 +779,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
...
@@ -779,7 +779,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
"FROM pg_rewrite r, pg_class c
\n
"
"FROM pg_rewrite r, pg_class c
\n
"
"WHERE c.relname='%s' AND c.oid = r.ev_class"
,
"WHERE c.relname='%s' AND c.oid = r.ev_class"
,
name
);
name
);
result3
=
PSQLexec
(
pset
,
buf
);
result3
=
PSQLexec
(
buf
);
if
(
!
result3
)
if
(
!
result3
)
error
=
true
;
error
=
true
;
else
else
...
@@ -794,7 +794,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
...
@@ -794,7 +794,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
"FROM pg_trigger t, pg_class c
\n
"
"FROM pg_trigger t, pg_class c
\n
"
"WHERE c.relname='%s' AND c.oid = t.tgrelid"
,
"WHERE c.relname='%s' AND c.oid = t.tgrelid"
,
name
);
name
);
result4
=
PSQLexec
(
pset
,
buf
);
result4
=
PSQLexec
(
buf
);
if
(
!
result4
)
if
(
!
result4
)
error
=
true
;
error
=
true
;
else
else
...
@@ -863,7 +863,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
...
@@ -863,7 +863,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
if
(
!
error
)
{
if
(
!
error
)
{
myopt
.
tuples_only
=
false
;
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 */
/* clean up */
...
@@ -906,7 +906,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
...
@@ -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.
* tries to fix this the painful way, hopefully outer joins will be done sometime.
*/
*/
bool
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
showTables
=
strchr
(
infotype
,
't'
)
!=
NULL
;
bool
showIndices
=
strchr
(
infotype
,
'i'
)
!=
NULL
;
bool
showIndices
=
strchr
(
infotype
,
'i'
)
!=
NULL
;
...
@@ -916,7 +916,7 @@ listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc
...
@@ -916,7 +916,7 @@ listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc
char
buf
[
3072
+
8
*
REGEXP_CUTOFF
];
char
buf
[
3072
+
8
*
REGEXP_CUTOFF
];
PGresult
*
res
;
PGresult
*
res
;
printQueryOpt
myopt
=
pset
->
popt
;
printQueryOpt
myopt
=
pset
.
popt
;
buf
[
0
]
=
'\0'
;
buf
[
0
]
=
'\0'
;
...
@@ -1093,20 +1093,24 @@ listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc
...
@@ -1093,20 +1093,24 @@ listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc
strcat
(
buf
,
"
\n
ORDER BY
\"
Name
\"
"
);
strcat
(
buf
,
"
\n
ORDER BY
\"
Name
\"
"
);
res
=
PSQLexec
(
pset
,
buf
);
res
=
PSQLexec
(
buf
);
if
(
!
res
)
if
(
!
res
)
return
false
;
return
false
;
if
(
PQntuples
(
res
)
==
0
)
if
(
PQntuples
(
res
)
==
0
&&
!
QUIET
())
fprintf
(
pset
->
queryFout
,
"No matching relations found.
\n
"
);
{
if
(
name
)
fprintf
(
pset
.
queryFout
,
"No matching relations found.
\n
"
);
else
fprintf
(
pset
.
queryFout
,
"No relations found.
\n
"
);
}
else
else
{
{
myopt
.
topt
.
tuples_only
=
false
;
myopt
.
topt
.
tuples_only
=
false
;
myopt
.
nullPrint
=
NULL
;
myopt
.
nullPrint
=
NULL
;
myopt
.
title
=
"List of relations"
;
myopt
.
title
=
"List of relations"
;
printQuery
(
res
,
&
myopt
,
pset
->
queryFout
);
printQuery
(
res
,
&
myopt
,
pset
.
queryFout
);
}
}
PQclear
(
res
);
PQclear
(
res
);
...
...
src/bin/psql/describe.h
View file @
7c9390ca
...
@@ -5,30 +5,30 @@
...
@@ -5,30 +5,30 @@
#include "settings.h"
#include "settings.h"
/* \da */
/* \da */
bool
describeAggregates
(
const
char
*
name
,
PsqlSettings
*
pset
);
bool
describeAggregates
(
const
char
*
name
);
/* \df */
/* \df */
bool
describeFunctions
(
const
char
*
name
,
PsqlSettings
*
pset
,
bool
verbose
);
bool
describeFunctions
(
const
char
*
name
,
bool
verbose
);
/* \dT */
/* \dT */
bool
describeTypes
(
const
char
*
name
,
PsqlSettings
*
pset
,
bool
verbose
);
bool
describeTypes
(
const
char
*
name
,
bool
verbose
);
/* \do */
/* \do */
bool
describeOperators
(
const
char
*
name
,
PsqlSettings
*
pset
);
bool
describeOperators
(
const
char
*
name
);
/* \z (or \dp) */
/* \z (or \dp) */
bool
permissionsList
(
const
char
*
name
,
PsqlSettings
*
pset
);
bool
permissionsList
(
const
char
*
name
);
/* \dd */
/* \dd */
bool
objectDescription
(
const
char
*
object
,
PsqlSettings
*
pset
);
bool
objectDescription
(
const
char
*
object
);
/* \d foo */
/* \d foo */
bool
describeTableDetails
(
const
char
*
name
,
PsqlSettings
*
pset
,
bool
desc
);
bool
describeTableDetails
(
const
char
*
name
,
bool
desc
);
/* \l */
/* \l */
bool
listAllDbs
(
PsqlSettings
*
pset
,
bool
desc
);
bool
listAllDbs
(
bool
desc
);
/* \dt, \di, \ds, \dS, etc. */
/* \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 */
#endif
/* DESCRIBE_H */
src/bin/psql/help.c
View file @
7c9390ca
...
@@ -149,7 +149,7 @@ struct winsize
...
@@ -149,7 +149,7 @@ struct winsize
#endif
#endif
void
void
slashUsage
(
PsqlSettings
*
pset
)
slashUsage
(
void
)
{
{
bool
usePipe
=
false
;
bool
usePipe
=
false
;
const
char
*
pagerenv
;
const
char
*
pagerenv
;
...
@@ -157,7 +157,7 @@ slashUsage(PsqlSettings *pset)
...
@@ -157,7 +157,7 @@ slashUsage(PsqlSettings *pset)
struct
winsize
screen_size
;
struct
winsize
screen_size
;
#ifdef TIOCGWINSZ
#ifdef TIOCGWINSZ
if
(
pset
->
notty
==
0
&&
if
(
pset
.
notty
==
0
&&
(
ioctl
(
fileno
(
stdout
),
TIOCGWINSZ
,
&
screen_size
)
==
-
1
||
(
ioctl
(
fileno
(
stdout
),
TIOCGWINSZ
,
&
screen_size
)
==
-
1
||
screen_size
.
ws_col
==
0
||
screen_size
.
ws_col
==
0
||
screen_size
.
ws_row
==
0
))
screen_size
.
ws_row
==
0
))
...
@@ -169,7 +169,7 @@ slashUsage(PsqlSettings *pset)
...
@@ -169,7 +169,7 @@ slashUsage(PsqlSettings *pset)
}
}
#endif
#endif
if
(
pset
->
notty
==
0
&&
if
(
pset
.
notty
==
0
&&
(
pagerenv
=
getenv
(
"PAGER"
))
&&
(
pagerenv
=
getenv
(
"PAGER"
))
&&
(
pagerenv
[
0
]
!=
'\0'
)
&&
(
pagerenv
[
0
]
!=
'\0'
)
&&
screen_size
.
ws_row
<=
36
&&
screen_size
.
ws_row
<=
36
&&
...
@@ -184,7 +184,7 @@ slashUsage(PsqlSettings *pset)
...
@@ -184,7 +184,7 @@ slashUsage(PsqlSettings *pset)
/* if you add/remove a line here, change the row test above */
/* if you add/remove a line here, change the row test above */
fprintf
(
fout
,
"
\\
? help
\n
"
);
fprintf
(
fout
,
"
\\
? help
\n
"
);
fprintf
(
fout
,
"
\\
c[onnect] [dbname|- [user|?]]
\n
"
fprintf
(
fout
,
"
\\
c[onnect] [dbname|- [user|?]]
\n
"
" connect to new database (currently '%s')
\n
"
,
PQdb
(
pset
->
db
));
" connect to new database (currently '%s')
\n
"
,
PQdb
(
pset
.
db
));
fprintf
(
fout
,
"
\\
copy ... perform SQL COPY with data stream to the client machine"
);
fprintf
(
fout
,
"
\\
copy ... perform SQL COPY with data stream to the client machine"
);
fprintf
(
fout
,
"
\\
copyright show PostgreSQL usage and distribution terms
\n
"
);
fprintf
(
fout
,
"
\\
copyright show PostgreSQL usage and distribution terms
\n
"
);
fprintf
(
fout
,
"
\\
d <table> describe table (or view, index, sequence)
\n
"
);
fprintf
(
fout
,
"
\\
d <table> describe table (or view, index, sequence)
\n
"
);
...
@@ -209,9 +209,10 @@ slashUsage(PsqlSettings *pset)
...
@@ -209,9 +209,10 @@ slashUsage(PsqlSettings *pset)
fprintf
(
fout
,
"
\\
qecho <text> write text to query output stream (see
\\
o)
\n
"
);
fprintf
(
fout
,
"
\\
qecho <text> write text to query output stream (see
\\
o)
\n
"
);
fprintf
(
fout
,
"
\\
r reset (clear) the query buffer
\n
"
);
fprintf
(
fout
,
"
\\
r reset (clear) the query buffer
\n
"
);
fprintf
(
fout
,
"
\\
s [fname] print history or save it in <fname>
\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
,
"
\\
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
,
"
\\
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
,
"
\\
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
,
"
\\
w <fname> write current query buffer to a file
\n
"
);
fprintf
(
fout
,
"
\\
z list table access permissions
\n
"
);
fprintf
(
fout
,
"
\\
z list table access permissions
\n
"
);
fprintf
(
fout
,
"
\\
! [cmd] shell escape or command
\n
"
);
fprintf
(
fout
,
"
\\
! [cmd] shell escape or command
\n
"
);
...
...
src/bin/psql/help.h
View file @
7c9390ca
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
void
usage
(
void
);
void
usage
(
void
);
void
slashUsage
(
PsqlSettings
*
pset
);
void
slashUsage
(
void
);
void
helpSQL
(
const
char
*
topic
);
void
helpSQL
(
const
char
*
topic
);
...
...
src/bin/psql/input.c
View file @
7c9390ca
...
@@ -29,6 +29,10 @@ char *
...
@@ -29,6 +29,10 @@ char *
gets_interactive
(
const
char
*
prompt
)
gets_interactive
(
const
char
*
prompt
)
{
{
char
*
s
;
char
*
s
;
#ifdef USE_HISTORY
const
char
*
var
;
static
char
*
prev_hist
=
NULL
;
#endif
#ifdef USE_READLINE
#ifdef USE_READLINE
if
(
useReadline
)
if
(
useReadline
)
...
@@ -44,8 +48,19 @@ gets_interactive(const char *prompt)
...
@@ -44,8 +48,19 @@ gets_interactive(const char *prompt)
#endif
#endif
#ifdef USE_HISTORY
#ifdef USE_HISTORY
if
(
useHistory
&&
s
&&
s
[
0
]
!=
'\0'
)
if
(
useHistory
&&
s
&&
s
[
0
]
!=
'\0'
)
add_history
(
s
);
{
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
#endif
return
s
;
return
s
;
...
@@ -93,14 +108,14 @@ gets_fromFile(FILE *source)
...
@@ -93,14 +108,14 @@ gets_fromFile(FILE *source)
* The only "flag" right now is 1 for use readline & history.
* The only "flag" right now is 1 for use readline & history.
*/
*/
void
void
initializeInput
(
int
flags
,
PsqlSettings
*
pset
)
initializeInput
(
int
flags
)
{
{
#ifdef USE_READLINE
#ifdef USE_READLINE
if
(
flags
==
1
)
if
(
flags
==
1
)
{
{
useReadline
=
true
;
useReadline
=
true
;
rl_readline_name
=
"psql"
;
rl_readline_name
=
"psql"
;
initialize_readline
(
&
(
pset
->
db
));
initialize_readline
(
&
(
pset
.
db
));
}
}
#endif
#endif
...
@@ -110,6 +125,7 @@ initializeInput(int flags, PsqlSettings *pset)
...
@@ -110,6 +125,7 @@ initializeInput(int flags, PsqlSettings *pset)
const
char
*
home
;
const
char
*
home
;
useHistory
=
true
;
useHistory
=
true
;
SetVariable
(
pset
.
vars
,
"HISTSIZE"
,
"500"
);
using_history
();
using_history
();
home
=
getenv
(
"HOME"
);
home
=
getenv
(
"HOME"
);
if
(
home
)
if
(
home
)
...
@@ -166,6 +182,9 @@ finishInput(void)
...
@@ -166,6 +182,9 @@ finishInput(void)
psql_history
=
(
char
*
)
malloc
(
strlen
(
home
)
+
20
);
psql_history
=
(
char
*
)
malloc
(
strlen
(
home
)
+
20
);
if
(
psql_history
)
if
(
psql_history
)
{
{
const
char
*
var
=
GetVariable
(
pset
.
vars
,
"HISTSIZE"
);
if
(
var
)
stifle_history
(
atoi
(
var
));
sprintf
(
psql_history
,
"%s/.psql_history"
,
home
);
sprintf
(
psql_history
,
"%s/.psql_history"
,
home
);
write_history
(
psql_history
);
write_history
(
psql_history
);
free
(
psql_history
);
free
(
psql_history
);
...
...
src/bin/psql/input.h
View file @
7c9390ca
...
@@ -42,7 +42,7 @@ char * gets_interactive(const char *prompt);
...
@@ -42,7 +42,7 @@ char * gets_interactive(const char *prompt);
char
*
gets_fromFile
(
FILE
*
source
);
char
*
gets_fromFile
(
FILE
*
source
);
void
initializeInput
(
int
flags
,
PsqlSettings
*
pset
);
void
initializeInput
(
int
flags
);
bool
saveHistory
(
const
char
*
fname
);
bool
saveHistory
(
const
char
*
fname
);
...
...
src/bin/psql/large_obj.c
View file @
7c9390ca
#include <config.h>
#include <c.h>
#include <c.h>
#include "large_obj.h"
#include "large_obj.h"
...
@@ -33,9 +32,9 @@ _my_notice_handler(void *arg, const char *message)
...
@@ -33,9 +32,9 @@ _my_notice_handler(void *arg, const char *message)
static
bool
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
;
PGresult
*
res
;
bool
commit
;
bool
commit
;
PQnoticeProcessor
old_notice_hook
;
PQnoticeProcessor
old_notice_hook
;
...
@@ -46,9 +45,9 @@ handle_transaction(PsqlSettings *pset)
...
@@ -46,9 +45,9 @@ handle_transaction(PsqlSettings *pset)
commit
=
(
var
&&
strcmp
(
var
,
"commit"
)
==
0
);
commit
=
(
var
&&
strcmp
(
var
,
"commit"
)
==
0
);
notice
[
0
]
=
'\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
)
if
(
!
res
)
return
false
;
return
false
;
...
@@ -58,7 +57,7 @@ handle_transaction(PsqlSettings *pset)
...
@@ -58,7 +57,7 @@ handle_transaction(PsqlSettings *pset)
(
commit
&&
strcmp
(
notice
,
"NOTICE: EndTransactionBlock and not inprogress/abort state
\n
"
)
!=
0
))
(
commit
&&
strcmp
(
notice
,
"NOTICE: EndTransactionBlock and not inprogress/abort state
\n
"
)
!=
0
))
fputs
(
notice
,
stderr
);
fputs
(
notice
,
stderr
);
}
}
else
if
(
!
GetVariableBool
(
pset
->
vars
,
"quiet"
))
else
if
(
!
QUIET
(
))
{
{
if
(
commit
)
if
(
commit
)
puts
(
"Warning: Your transaction in progress has been committed."
);
puts
(
"Warning: Your transaction in progress has been committed."
);
...
@@ -66,7 +65,7 @@ handle_transaction(PsqlSettings *pset)
...
@@ -66,7 +65,7 @@ handle_transaction(PsqlSettings *pset)
puts
(
"Warning: Your transaction in progress has been rolled back."
);
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
;
return
true
;
}
}
...
@@ -78,43 +77,43 @@ handle_transaction(PsqlSettings *pset)
...
@@ -78,43 +77,43 @@ handle_transaction(PsqlSettings *pset)
* Write a large object to a file
* Write a large object to a file
*/
*/
bool
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
;
PGresult
*
res
;
int
status
;
int
status
;
bool
own_transaction
=
true
;
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
)
if
(
var
&&
strcmp
(
var
,
"nothing"
)
==
0
)
own_transaction
=
false
;
own_transaction
=
false
;
if
(
!
pset
->
db
)
if
(
!
pset
.
db
)
{
{
if
(
!
pset
->
cur_cmd_interactive
)
if
(
!
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"%s: "
,
pset
->
progname
);
fprintf
(
stderr
,
"%s: "
,
pset
.
progname
);
fputs
(
"
\\
lo_export: not connected to a database
\n
"
,
stderr
);
fputs
(
"
\\
lo_export: not connected to a database
\n
"
,
stderr
);
return
false
;
return
false
;
}
}
if
(
own_transaction
)
if
(
own_transaction
)
{
{
if
(
!
handle_transaction
(
pset
))
if
(
!
handle_transaction
())
return
false
;
return
false
;
if
(
!
(
res
=
PSQLexec
(
pset
,
"BEGIN"
)))
if
(
!
(
res
=
PSQLexec
(
"BEGIN"
)))
return
false
;
return
false
;
PQclear
(
res
);
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
)
if
(
status
!=
1
)
{
/* of course this status is documented
{
/* of course this status is documented
* nowhere :( */
* nowhere :( */
fputs
(
PQerrorMessage
(
pset
->
db
),
stderr
);
fputs
(
PQerrorMessage
(
pset
.
db
),
stderr
);
if
(
own_transaction
)
if
(
own_transaction
)
{
{
res
=
PQexec
(
pset
->
db
,
"ROLLBACK"
);
res
=
PQexec
(
pset
.
db
,
"ROLLBACK"
);
PQclear
(
res
);
PQclear
(
res
);
}
}
return
false
;
return
false
;
...
@@ -122,9 +121,9 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
...
@@ -122,9 +121,9 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
if
(
own_transaction
)
if
(
own_transaction
)
{
{
if
(
!
(
res
=
PSQLexec
(
pset
,
"COMMIT"
)))
if
(
!
(
res
=
PSQLexec
(
"COMMIT"
)))
{
{
res
=
PQexec
(
pset
->
db
,
"ROLLBACK"
);
res
=
PQexec
(
pset
.
db
,
"ROLLBACK"
);
PQclear
(
res
);
PQclear
(
res
);
return
false
;
return
false
;
}
}
...
@@ -132,7 +131,7 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
...
@@ -132,7 +131,7 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
PQclear
(
res
);
PQclear
(
res
);
}
}
fprintf
(
pset
->
queryFout
,
"lo_export
\n
"
);
fprintf
(
pset
.
queryFout
,
"lo_export
\n
"
);
return
true
;
return
true
;
}
}
...
@@ -145,44 +144,44 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
...
@@ -145,44 +144,44 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
* Copy large object from file to database
* Copy large object from file to database
*/
*/
bool
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
;
PGresult
*
res
;
Oid
loid
;
Oid
loid
;
char
buf
[
1024
];
char
buf
[
1024
];
unsigned
int
i
;
unsigned
int
i
;
bool
own_transaction
=
true
;
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
)
if
(
var
&&
strcmp
(
var
,
"nothing"
)
==
0
)
own_transaction
=
false
;
own_transaction
=
false
;
if
(
!
pset
->
db
)
if
(
!
pset
.
db
)
{
{
if
(
!
pset
->
cur_cmd_interactive
)
if
(
!
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"%s: "
,
pset
->
progname
);
fprintf
(
stderr
,
"%s: "
,
pset
.
progname
);
fputs
(
"
\\
lo_import: not connected to a database
\n
"
,
stderr
);
fputs
(
"
\\
lo_import: not connected to a database
\n
"
,
stderr
);
return
false
;
return
false
;
}
}
if
(
own_transaction
)
if
(
own_transaction
)
{
{
if
(
!
handle_transaction
(
pset
))
if
(
!
handle_transaction
())
return
false
;
return
false
;
if
(
!
(
res
=
PSQLexec
(
pset
,
"BEGIN"
)))
if
(
!
(
res
=
PSQLexec
(
"BEGIN"
)))
return
false
;
return
false
;
PQclear
(
res
);
PQclear
(
res
);
}
}
loid
=
lo_import
(
pset
->
db
,
(
char
*
)
filename_arg
);
loid
=
lo_import
(
pset
.
db
,
(
char
*
)
filename_arg
);
if
(
loid
==
InvalidOid
)
if
(
loid
==
InvalidOid
)
{
{
fputs
(
PQerrorMessage
(
pset
->
db
),
stderr
);
fputs
(
PQerrorMessage
(
pset
.
db
),
stderr
);
if
(
own_transaction
)
if
(
own_transaction
)
{
{
res
=
PQexec
(
pset
->
db
,
"ROLLBACK"
);
res
=
PQexec
(
pset
.
db
,
"ROLLBACK"
);
PQclear
(
res
);
PQclear
(
res
);
}
}
return
false
;
return
false
;
...
@@ -199,11 +198,11 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
...
@@ -199,11 +198,11 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
strncat
(
buf
,
&
comment_arg
[
i
],
1
);
strncat
(
buf
,
&
comment_arg
[
i
],
1
);
strcat
(
buf
,
"')"
);
strcat
(
buf
,
"')"
);
if
(
!
(
res
=
PSQLexec
(
pset
,
buf
)))
if
(
!
(
res
=
PSQLexec
(
buf
)))
{
{
if
(
own_transaction
)
if
(
own_transaction
)
{
{
res
=
PQexec
(
pset
->
db
,
"ROLLBACK"
);
res
=
PQexec
(
pset
.
db
,
"ROLLBACK"
);
PQclear
(
res
);
PQclear
(
res
);
}
}
return
false
;
return
false
;
...
@@ -212,9 +211,9 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
...
@@ -212,9 +211,9 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
if
(
own_transaction
)
if
(
own_transaction
)
{
{
if
(
!
(
res
=
PSQLexec
(
pset
,
"COMMIT"
)))
if
(
!
(
res
=
PSQLexec
(
"COMMIT"
)))
{
{
res
=
PQexec
(
pset
->
db
,
"ROLLBACK"
);
res
=
PQexec
(
pset
.
db
,
"ROLLBACK"
);
PQclear
(
res
);
PQclear
(
res
);
return
false
;
return
false
;
}
}
...
@@ -223,8 +222,9 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
...
@@ -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
);
fprintf
(
pset
.
queryFout
,
"lo_import %d
\n
"
,
loid
);
pset
->
lastOid
=
loid
;
sprintf
(
buf
,
"%u"
,
(
unsigned
int
)
loid
);
SetVariable
(
pset
.
vars
,
"LASTOID"
,
buf
);
return
true
;
return
true
;
}
}
...
@@ -237,44 +237,44 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
...
@@ -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
* removes a large object out of the database
*/
*/
bool
bool
do_lo_unlink
(
PsqlSettings
*
pset
,
const
char
*
loid_arg
)
do_lo_unlink
(
const
char
*
loid_arg
)
{
{
PGresult
*
res
;
PGresult
*
res
;
int
status
;
int
status
;
Oid
loid
=
(
Oid
)
atol
(
loid_arg
);
Oid
loid
=
(
Oid
)
atol
(
loid_arg
);
char
buf
[
256
];
char
buf
[
256
];
bool
own_transaction
=
true
;
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
)
if
(
var
&&
strcmp
(
var
,
"nothing"
)
==
0
)
own_transaction
=
false
;
own_transaction
=
false
;
if
(
!
pset
->
db
)
if
(
!
pset
.
db
)
{
{
if
(
!
pset
->
cur_cmd_interactive
)
if
(
!
pset
.
cur_cmd_interactive
)
fprintf
(
stderr
,
"%s: "
,
pset
->
progname
);
fprintf
(
stderr
,
"%s: "
,
pset
.
progname
);
fputs
(
"
\\
lo_unlink: not connected to a database
\n
"
,
stderr
);
fputs
(
"
\\
lo_unlink: not connected to a database
\n
"
,
stderr
);
return
false
;
return
false
;
}
}
if
(
own_transaction
)
if
(
own_transaction
)
{
{
if
(
!
handle_transaction
(
pset
))
if
(
!
handle_transaction
())
return
false
;
return
false
;
if
(
!
(
res
=
PSQLexec
(
pset
,
"BEGIN"
)))
if
(
!
(
res
=
PSQLexec
(
"BEGIN"
)))
return
false
;
return
false
;
PQclear
(
res
);
PQclear
(
res
);
}
}
status
=
lo_unlink
(
pset
->
db
,
loid
);
status
=
lo_unlink
(
pset
.
db
,
loid
);
if
(
status
==
-
1
)
if
(
status
==
-
1
)
{
{
fputs
(
PQerrorMessage
(
pset
->
db
),
stderr
);
fputs
(
PQerrorMessage
(
pset
.
db
),
stderr
);
if
(
own_transaction
)
if
(
own_transaction
)
{
{
res
=
PQexec
(
pset
->
db
,
"ROLLBACK"
);
res
=
PQexec
(
pset
.
db
,
"ROLLBACK"
);
PQclear
(
res
);
PQclear
(
res
);
}
}
return
false
;
return
false
;
...
@@ -282,11 +282,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
...
@@ -282,11 +282,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
/* remove the comment as well */
/* remove the comment as well */
sprintf
(
buf
,
"DELETE FROM pg_description WHERE objoid = %d"
,
loid
);
sprintf
(
buf
,
"DELETE FROM pg_description WHERE objoid = %d"
,
loid
);
if
(
!
(
res
=
PSQLexec
(
pset
,
buf
)))
if
(
!
(
res
=
PSQLexec
(
buf
)))
{
{
if
(
own_transaction
)
if
(
own_transaction
)
{
{
res
=
PQexec
(
pset
->
db
,
"ROLLBACK"
);
res
=
PQexec
(
pset
.
db
,
"ROLLBACK"
);
PQclear
(
res
);
PQclear
(
res
);
}
}
return
false
;
return
false
;
...
@@ -295,9 +295,9 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
...
@@ -295,9 +295,9 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
if
(
own_transaction
)
if
(
own_transaction
)
{
{
if
(
!
(
res
=
PSQLexec
(
pset
,
"COMMIT"
)))
if
(
!
(
res
=
PSQLexec
(
"COMMIT"
)))
{
{
res
=
PQexec
(
pset
->
db
,
"ROLLBACK"
);
res
=
PQexec
(
pset
.
db
,
"ROLLBACK"
);
PQclear
(
res
);
PQclear
(
res
);
return
false
;
return
false
;
}
}
...
@@ -305,7 +305,7 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
...
@@ -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
;
return
true
;
}
}
...
@@ -318,11 +318,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
...
@@ -318,11 +318,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
* Show all large objects in database with comments
* Show all large objects in database with comments
*/
*/
bool
bool
do_lo_list
(
PsqlSettings
*
pset
)
do_lo_list
(
void
)
{
{
PGresult
*
res
;
PGresult
*
res
;
char
buf
[
1024
];
char
buf
[
1024
];
printQueryOpt
myopt
=
pset
->
popt
;
printQueryOpt
myopt
=
pset
.
popt
;
strcpy
(
buf
,
strcpy
(
buf
,
"SELECT usename as
\"
Owner
\"
, substring(relname from 5) as
\"
ID
\"
,
\n
"
"SELECT usename as
\"
Owner
\"
, substring(relname from 5) as
\"
ID
\"
,
\n
"
...
@@ -336,7 +336,7 @@ do_lo_list(PsqlSettings *pset)
...
@@ -336,7 +336,7 @@ do_lo_list(PsqlSettings *pset)
"WHERE not exists (select 1 from pg_user where usesysid = relowner) AND relkind = 'l'
\n
"
"WHERE not exists (select 1 from pg_user where usesysid = relowner) AND relkind = 'l'
\n
"
"ORDER BY
\"
ID
\"
"
);
"ORDER BY
\"
ID
\"
"
);
res
=
PSQLexec
(
pset
,
buf
);
res
=
PSQLexec
(
buf
);
if
(
!
res
)
if
(
!
res
)
return
false
;
return
false
;
...
@@ -344,7 +344,7 @@ do_lo_list(PsqlSettings *pset)
...
@@ -344,7 +344,7 @@ do_lo_list(PsqlSettings *pset)
myopt
.
nullPrint
=
NULL
;
myopt
.
nullPrint
=
NULL
;
myopt
.
title
=
"Large objects"
;
myopt
.
title
=
"Large objects"
;
printQuery
(
res
,
&
myopt
,
pset
->
queryFout
);
printQuery
(
res
,
&
myopt
,
pset
.
queryFout
);
PQclear
(
res
);
PQclear
(
res
);
return
true
;
return
true
;
...
...
src/bin/psql/large_obj.h
View file @
7c9390ca
...
@@ -2,11 +2,10 @@
...
@@ -2,11 +2,10 @@
#define LARGE_OBJ_H
#define LARGE_OBJ_H
#include <c.h>
#include <c.h>
#include "settings.h"
bool
do_lo_export
(
PsqlSettings
*
pset
,
const
char
*
loid_arg
,
const
char
*
filename_arg
);
bool
do_lo_export
(
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_import
(
const
char
*
filename_arg
,
const
char
*
comment_arg
);
bool
do_lo_unlink
(
PsqlSettings
*
pset
,
const
char
*
loid_arg
);
bool
do_lo_unlink
(
const
char
*
loid_arg
);
bool
do_lo_list
(
PsqlSettings
*
pset
);
bool
do_lo_list
(
void
);
#endif
/* LARGE_OBJ_H */
#endif
/* LARGE_OBJ_H */
src/bin/psql/mainloop.c
View file @
7c9390ca
#include <config.h>
#include <c.h>
#include <c.h>
#include "mainloop.h"
#include "mainloop.h"
...
@@ -26,7 +25,7 @@
...
@@ -26,7 +25,7 @@
* FIXME: rewrite this whole thing with flex
* FIXME: rewrite this whole thing with flex
*/
*/
int
int
MainLoop
(
PsqlSettings
*
pset
,
FILE
*
source
)
MainLoop
(
FILE
*
source
)
{
{
PQExpBuffer
query_buf
;
/* buffer for query being accumulated */
PQExpBuffer
query_buf
;
/* buffer for query being accumulated */
PQExpBuffer
previous_buf
;
/* if there isn't anything in the new buffer
PQExpBuffer
previous_buf
;
/* if there isn't anything in the new buffer
...
@@ -36,13 +35,14 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -36,13 +35,14 @@ MainLoop(PsqlSettings *pset, FILE *source)
int
successResult
=
EXIT_SUCCESS
;
int
successResult
=
EXIT_SUCCESS
;
backslashResult
slashCmdStatus
;
backslashResult
slashCmdStatus
;
bool
eof
=
false
;
/* end of our command input? */
bool
success
;
bool
success
;
char
in_quote
;
/* == 0 for no in_quote */
char
in_quote
;
/* == 0 for no in_quote */
bool
was_bslash
;
/* backslash */
bool
was_bslash
;
/* backslash */
bool
xcomment
;
/* in extended comment */
bool
xcomment
;
/* in extended comment */
int
paren_level
;
int
paren_level
;
unsigned
int
query_start
;
unsigned
int
query_start
;
int
count_eof
;
const
char
*
var
;
int
i
,
int
i
,
prevlen
,
prevlen
,
...
@@ -56,12 +56,12 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -56,12 +56,12 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* Save old settings */
/* Save old settings */
prev_cmd_source
=
pset
->
cur_cmd_source
;
prev_cmd_source
=
pset
.
cur_cmd_source
;
prev_cmd_interactive
=
pset
->
cur_cmd_interactive
;
prev_cmd_interactive
=
pset
.
cur_cmd_interactive
;
/* Establish new source */
/* Establish new source */
pset
->
cur_cmd_source
=
source
;
pset
.
cur_cmd_source
=
source
;
pset
->
cur_cmd_interactive
=
((
source
==
stdin
)
&&
!
pset
->
notty
);
pset
.
cur_cmd_interactive
=
((
source
==
stdin
)
&&
!
pset
.
notty
);
query_buf
=
createPQExpBuffer
();
query_buf
=
createPQExpBuffer
();
...
@@ -79,7 +79,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -79,7 +79,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* main loop to get queries and execute them */
/* main loop to get queries and execute them */
while
(
!
eof
)
while
(
1
)
{
{
if
(
slashCmdStatus
==
CMD_NEWEDIT
)
if
(
slashCmdStatus
==
CMD_NEWEDIT
)
{
{
...
@@ -102,7 +102,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -102,7 +102,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
* otherwise, set interactive prompt if necessary and get
* otherwise, set interactive prompt if necessary and get
* another line
* another line
*/
*/
if
(
pset
->
cur_cmd_interactive
)
if
(
pset
.
cur_cmd_interactive
)
{
{
int
prompt_status
;
int
prompt_status
;
...
@@ -117,7 +117,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -117,7 +117,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
else
else
prompt_status
=
PROMPT_READY
;
prompt_status
=
PROMPT_READY
;
line
=
gets_interactive
(
get_prompt
(
p
set
,
p
rompt_status
));
line
=
gets_interactive
(
get_prompt
(
prompt_status
));
}
}
else
else
line
=
gets_fromFile
(
source
);
line
=
gets_fromFile
(
source
);
...
@@ -125,7 +125,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -125,7 +125,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* Setting this will not have effect until next line. */
/* 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
* query_buf holds query already accumulated. line is the
...
@@ -137,14 +137,47 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -137,14 +137,47 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* No more input. Time to quit, or \i done */
/* No more input. Time to quit, or \i done */
if
(
line
==
NULL
)
if
(
line
==
NULL
)
{
{
if
(
GetVariableBool
(
pset
->
vars
,
"echo"
)
&&
!
GetVariableBool
(
pset
->
vars
,
"quiet"
))
if
(
pset
.
cur_cmd_interactive
)
puts
(
"EOF"
);
{
else
if
(
pset
->
cur_cmd_interactive
)
bool
getout
=
true
;
putc
(
'\n'
,
stdout
);
/* just newline */
/* 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 */
}
eof
=
true
;
if
(
getout
)
continue
;
{
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 */
/* strip trailing backslashes, they don't have a clear meaning */
while
(
1
)
while
(
1
)
...
@@ -164,11 +197,11 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -164,11 +197,11 @@ MainLoop(PsqlSettings *pset, FILE *source)
continue
;
continue
;
}
}
/* echo back if flag is set */
/* echo back if input is from file and flag is set */
var
=
GetVariable
(
pset
.
vars
,
"ECHO"
);
if
(
!
pset
->
cur_cmd_interactive
&&
GetVariableBool
(
pset
->
vars
,
"echo"
)
)
if
(
var
&&
strcmp
(
var
,
"full"
)
==
0
)
puts
(
line
);
puts
(
line
);
fflush
(
stdout
);
len
=
strlen
(
line
);
len
=
strlen
(
line
);
query_start
=
0
;
query_start
=
0
;
...
@@ -236,8 +269,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -236,8 +269,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* colon -> substitute variable */
/* colon -> substitute variable */
/* we need to be on the watch for the '::' operator */
/* we need to be on the watch for the '::' operator */
else
if
(
line
[
i
]
==
':'
&&
!
was_bslash
&&
else
if
(
line
[
i
]
==
':'
&&
!
was_bslash
&&
strspn
(
line
+
i
+
thislen
,
VALID_VARIABLE_CHARS
)
>
0
&&
strspn
(
line
+
i
+
thislen
,
VALID_VARIABLE_CHARS
)
>
0
(
prevlen
>
0
&&
line
[
i
-
prevlen
]
!=
':'
)
)
)
{
{
size_t
in_length
,
size_t
in_length
,
...
@@ -250,24 +282,35 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -250,24 +282,35 @@ MainLoop(PsqlSettings *pset, FILE *source)
in_length
=
strspn
(
&
line
[
i
+
thislen
],
VALID_VARIABLE_CHARS
);
in_length
=
strspn
(
&
line
[
i
+
thislen
],
VALID_VARIABLE_CHARS
);
after
=
line
[
i
+
thislen
+
in_length
];
after
=
line
[
i
+
thislen
+
in_length
];
line
[
i
+
thislen
+
in_length
]
=
'\0'
;
line
[
i
+
thislen
+
in_length
]
=
'\0'
;
value
=
interpolate_var
(
&
line
[
i
+
thislen
],
pset
);
out_length
=
strlen
(
value
);
new
=
malloc
(
len
+
out_length
-
(
1
+
in_length
)
+
1
);
if
(
!
new
)
{
perror
(
"malloc"
);
exit
(
EXIT_FAILURE
);
}
sprintf
(
new
,
"%.*s%s%c"
,
i
,
line
,
value
,
after
);
if
(
after
)
strcat
(
new
,
line
+
i
+
1
+
in_length
+
1
);
free
(
line
);
/* if the variable doesn't exist we'll leave the string as is */
line
=
new
;
value
=
GetVariable
(
pset
.
vars
,
&
line
[
i
+
thislen
]);
len
=
strlen
(
new
);
if
(
value
)
continue
;
/* reparse the just substituted */
{
out_length
=
strlen
(
value
);
new
=
malloc
(
len
+
out_length
-
(
1
+
in_length
)
+
1
);
if
(
!
new
)
{
perror
(
"malloc"
);
exit
(
EXIT_FAILURE
);
}
sprintf
(
new
,
"%.*s%s%c"
,
i
,
line
,
value
,
after
);
if
(
after
)
strcat
(
new
,
line
+
i
+
1
+
in_length
+
1
);
free
(
line
);
line
=
new
;
len
=
strlen
(
new
);
continue
;
/* reparse the just substituted */
}
else
{
/* restore overwritten character */
line
[
i
+
thislen
+
in_length
]
=
after
;
/* move on ... */
}
}
}
/* semicolon? then send query */
/* semicolon? then send query */
...
@@ -288,7 +331,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -288,7 +331,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
}
}
/* execute query */
/* execute query */
success
=
SendQuery
(
pset
,
query_buf
->
data
);
success
=
SendQuery
(
query_buf
->
data
);
slashCmdStatus
=
success
?
CMD_SEND
:
CMD_ERROR
;
slashCmdStatus
=
success
?
CMD_SEND
:
CMD_ERROR
;
resetPQExpBuffer
(
previous_buf
);
resetPQExpBuffer
(
previous_buf
);
...
@@ -314,7 +357,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -314,7 +357,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
paren_level
=
0
;
paren_level
=
0
;
line
[
i
-
prevlen
]
=
'\0'
;
/* overwrites backslash */
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'
)
if
(
line
[
query_start
+
strspn
(
line
+
query_start
,
"
\t
"
)]
!=
'\0'
)
{
{
/*
/*
...
@@ -328,7 +371,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -328,7 +371,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
}
}
/* handle backslash command */
/* handle backslash command */
slashCmdStatus
=
HandleSlashCmds
(
pset
,
&
line
[
i
],
slashCmdStatus
=
HandleSlashCmds
(
&
line
[
i
],
query_buf
->
len
>
0
?
query_buf
:
previous_buf
,
query_buf
->
len
>
0
?
query_buf
:
previous_buf
,
&
end_of_cmd
);
&
end_of_cmd
);
...
@@ -342,7 +385,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -342,7 +385,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
if
(
slashCmdStatus
==
CMD_SEND
)
if
(
slashCmdStatus
==
CMD_SEND
)
{
{
success
=
SendQuery
(
pset
,
query_buf
->
data
);
success
=
SendQuery
(
query_buf
->
data
);
query_start
=
i
+
thislen
;
query_start
=
i
+
thislen
;
resetPQExpBuffer
(
previous_buf
);
resetPQExpBuffer
(
previous_buf
);
...
@@ -350,14 +393,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -350,14 +393,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
resetPQExpBuffer
(
query_buf
);
resetPQExpBuffer
(
query_buf
);
}
}
/* is there anything left after the backslash command? */
/* process anything left after the backslash command */
if
(
end_of_cmd
)
i
+=
end_of_cmd
-
&
line
[
i
];
{
query_start
=
i
;
i
+=
end_of_cmd
-
&
line
[
i
];
query_start
=
i
;
}
else
break
;
}
}
...
@@ -387,9 +425,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -387,9 +425,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* In single line mode, send off the query if any */
/* 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
;
slashCmdStatus
=
success
?
CMD_SEND
:
CMD_ERROR
;
resetPQExpBuffer
(
previous_buf
);
resetPQExpBuffer
(
previous_buf
);
appendPQExpBufferStr
(
previous_buf
,
query_buf
->
data
);
appendPQExpBufferStr
(
previous_buf
,
query_buf
->
data
);
...
@@ -397,7 +435,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -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
;
successResult
=
EXIT_USER
;
break
;
break
;
...
@@ -405,18 +443,18 @@ MainLoop(PsqlSettings *pset, FILE *source)
...
@@ -405,18 +443,18 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* Have we lost the db connection? */
/* 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
;
successResult
=
EXIT_BADCONN
;
break
;
break
;
}
}
}
/* while !
EOF
*/
}
/* while !
endofprogram
*/
destroyPQExpBuffer
(
query_buf
);
destroyPQExpBuffer
(
query_buf
);
destroyPQExpBuffer
(
previous_buf
);
destroyPQExpBuffer
(
previous_buf
);
pset
->
cur_cmd_source
=
prev_cmd_source
;
pset
.
cur_cmd_source
=
prev_cmd_source
;
pset
->
cur_cmd_interactive
=
prev_cmd_interactive
;
pset
.
cur_cmd_interactive
=
prev_cmd_interactive
;
return
successResult
;
return
successResult
;
}
/* MainLoop() */
}
/* MainLoop() */
src/bin/psql/mainloop.h
View file @
7c9390ca
...
@@ -2,9 +2,7 @@
...
@@ -2,9 +2,7 @@
#define MAINLOOP_H
#define MAINLOOP_H
#include <stdio.h>
#include <stdio.h>
#include "settings.h"
int
int
MainLoop
(
FILE
*
source
);
MainLoop
(
PsqlSettings
*
pset
,
FILE
*
source
);
#endif
/* MAINLOOP_H */
#endif
/* MAINLOOP_H */
src/bin/psql/prompt.c
View file @
7c9390ca
#include <config.h>
#include <c.h>
#include <c.h>
#include "prompt.h"
#include "prompt.h"
...
@@ -10,6 +9,7 @@
...
@@ -10,6 +9,7 @@
#include "settings.h"
#include "settings.h"
#include "common.h"
#include "common.h"
#include "variables.h"
#ifdef WIN32
#ifdef WIN32
#define popen(x,y) _popen(x,y)
#define popen(x,y) _popen(x,y)
...
@@ -22,7 +22,7 @@
...
@@ -22,7 +22,7 @@
* get_prompt
* get_prompt
*
*
* Returns a statically allocated prompt made by interpolating certain
* Returns a statically allocated prompt made by interpolating certain
* tcsh style escape sequences into pset->vars "
prompt
1|2|3".
* tcsh style escape sequences into pset->vars "
PROMPT
1|2|3".
* (might not be completely multibyte safe)
* (might not be completely multibyte safe)
*
*
* Defined interpolations are:
* Defined interpolations are:
...
@@ -46,8 +46,7 @@
...
@@ -46,8 +46,7 @@
*
*
* %`command` - The result of executing command in /bin/sh with trailing
* %`command` - The result of executing command in /bin/sh with trailing
* newline stripped.
* newline stripped.
* %$name$ - The value of the psql/environment/magic varible 'name'
* %$name$ - The value of the psql variable 'name'
* (same rules as for, e.g., \echo $foo)
* (those will not be rescanned for more escape sequences!)
* (those will not be rescanned for more escape sequences!)
*
*
*
*
...
@@ -56,7 +55,7 @@
...
@@ -56,7 +55,7 @@
*--------------------------
*--------------------------
*/
*/
const
char
*
const
char
*
get_prompt
(
PsqlSettings
*
pset
,
promptStatus_t
status
)
get_prompt
(
promptStatus_t
status
)
{
{
#define MAX_PROMPT_SIZE 256
#define MAX_PROMPT_SIZE 256
static
char
destination
[
MAX_PROMPT_SIZE
+
1
];
static
char
destination
[
MAX_PROMPT_SIZE
+
1
];
...
@@ -66,11 +65,11 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
...
@@ -66,11 +65,11 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
const
char
*
prompt_string
;
const
char
*
prompt_string
;
if
(
status
==
PROMPT_READY
)
if
(
status
==
PROMPT_READY
)
prompt_string
=
GetVariable
(
pset
->
vars
,
"prompt
1"
);
prompt_string
=
GetVariable
(
pset
.
vars
,
"PROMPT
1"
);
else
if
(
status
==
PROMPT_CONTINUE
||
status
==
PROMPT_SINGLEQUOTE
||
status
==
PROMPT_DOUBLEQUOTE
||
status
==
PROMPT_COMMENT
)
else
if
(
status
==
PROMPT_CONTINUE
||
status
==
PROMPT_SINGLEQUOTE
||
status
==
PROMPT_DOUBLEQUOTE
||
status
==
PROMPT_COMMENT
)
prompt_string
=
GetVariable
(
pset
->
vars
,
"prompt
2"
);
prompt_string
=
GetVariable
(
pset
.
vars
,
"PROMPT
2"
);
else
if
(
status
==
PROMPT_COPY
)
else
if
(
status
==
PROMPT_COPY
)
prompt_string
=
GetVariable
(
pset
->
vars
,
"prompt
3"
);
prompt_string
=
GetVariable
(
pset
.
vars
,
"PROMPT
3"
);
else
else
prompt_string
=
"? "
;
prompt_string
=
"? "
;
...
@@ -92,31 +91,31 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
...
@@ -92,31 +91,31 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
/* Current database */
/* Current database */
case
'/'
:
case
'/'
:
if
(
pset
->
db
)
if
(
pset
.
db
)
strncpy
(
buf
,
PQdb
(
pset
->
db
),
MAX_PROMPT_SIZE
);
strncpy
(
buf
,
PQdb
(
pset
.
db
),
MAX_PROMPT_SIZE
);
break
;
break
;
case
'~'
:
case
'~'
:
{
{
const
char
*
var
;
const
char
*
var
;
if
(
pset
->
db
)
if
(
pset
.
db
)
{
{
if
(
strcmp
(
PQdb
(
pset
->
db
),
PQuser
(
pset
->
db
))
==
0
||
if
(
strcmp
(
PQdb
(
pset
.
db
),
PQuser
(
pset
.
db
))
==
0
||
((
var
=
getenv
(
"PGDATABASE"
))
&&
strcmp
(
var
,
PQdb
(
pset
->
db
))
==
0
))
((
var
=
getenv
(
"PGDATABASE"
))
&&
strcmp
(
var
,
PQdb
(
pset
.
db
))
==
0
))
strcpy
(
buf
,
"~"
);
strcpy
(
buf
,
"~"
);
else
else
strncpy
(
buf
,
PQdb
(
pset
->
db
),
MAX_PROMPT_SIZE
);
strncpy
(
buf
,
PQdb
(
pset
.
db
),
MAX_PROMPT_SIZE
);
}
}
break
;
break
;
}
}
/* DB server hostname (long/short) */
/* DB server hostname (long/short) */
case
'M'
:
case
'M'
:
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'
)
if
(
*
p
==
'm'
)
buf
[
strcspn
(
buf
,
"."
)]
=
'\0'
;
buf
[
strcspn
(
buf
,
"."
)]
=
'\0'
;
}
}
...
@@ -126,13 +125,13 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
...
@@ -126,13 +125,13 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
break
;
break
;
/* DB server port number */
/* DB server port number */
case
'>'
:
case
'>'
:
if
(
pset
->
db
&&
PQport
(
pset
->
db
))
if
(
pset
.
db
&&
PQport
(
pset
.
db
))
strncpy
(
buf
,
PQport
(
pset
->
db
),
MAX_PROMPT_SIZE
);
strncpy
(
buf
,
PQport
(
pset
.
db
),
MAX_PROMPT_SIZE
);
break
;
break
;
/* DB server user name */
/* DB server user name */
case
'n'
:
case
'n'
:
if
(
pset
->
db
)
if
(
pset
.
db
)
strncpy
(
buf
,
PQuser
(
pset
->
db
),
MAX_PROMPT_SIZE
);
strncpy
(
buf
,
PQuser
(
pset
.
db
),
MAX_PROMPT_SIZE
);
break
;
break
;
case
'0'
:
case
'0'
:
...
@@ -159,9 +158,9 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
...
@@ -159,9 +158,9 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
switch
(
status
)
switch
(
status
)
{
{
case
PROMPT_READY
:
case
PROMPT_READY
:
if
(
!
pset
->
db
)
if
(
!
pset
.
db
)
buf
[
0
]
=
'!'
;
buf
[
0
]
=
'!'
;
else
if
(
!
GetVariableBool
(
pset
->
vars
,
"singleline
"
))
else
if
(
!
GetVariableBool
(
pset
.
vars
,
"SINGLELINE
"
))
buf
[
0
]
=
'='
;
buf
[
0
]
=
'='
;
else
else
buf
[
0
]
=
'^'
;
buf
[
0
]
=
'^'
;
...
@@ -189,7 +188,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
...
@@ -189,7 +188,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
case
'#'
:
case
'#'
:
{
{
if
(
pset
->
db
&&
strcmp
(
PQuser
(
pset
->
db
),
"postgres"
)
==
0
)
if
(
pset
.
db
&&
strcmp
(
PQuser
(
pset
.
db
),
"postgres"
)
==
0
)
buf
[
0
]
=
'#'
;
buf
[
0
]
=
'#'
;
else
else
buf
[
0
]
=
'>'
;
buf
[
0
]
=
'>'
;
...
@@ -230,7 +229,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
...
@@ -230,7 +229,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
name
=
strdup
(
p
+
1
);
name
=
strdup
(
p
+
1
);
nameend
=
strcspn
(
name
,
"$"
);
nameend
=
strcspn
(
name
,
"$"
);
name
[
nameend
]
=
'\0'
;
name
[
nameend
]
=
'\0'
;
val
=
interpolate_var
(
name
,
pset
);
val
=
GetVariable
(
pset
.
vars
,
name
);
if
(
val
)
if
(
val
)
strncpy
(
buf
,
val
,
MAX_PROMPT_SIZE
);
strncpy
(
buf
,
val
,
MAX_PROMPT_SIZE
);
free
(
name
);
free
(
name
);
...
...
src/bin/psql/prompt.h
View file @
7c9390ca
...
@@ -14,7 +14,7 @@ typedef enum _promptStatus
...
@@ -14,7 +14,7 @@ typedef enum _promptStatus
}
promptStatus_t
;
}
promptStatus_t
;
const
char
*
const
char
*
get_prompt
(
PsqlSettings
*
pset
,
promptStatus_t
status
);
get_prompt
(
promptStatus_t
status
);
#endif
/* PROMPT_H */
#endif
/* PROMPT_H */
src/bin/psql/settings.h
View file @
7c9390ca
...
@@ -43,11 +43,13 @@ typedef struct _psqlSettings
...
@@ -43,11 +43,13 @@ typedef struct _psqlSettings
bool
has_client_encoding
;
/* was PGCLIENTENCODING set on
bool
has_client_encoding
;
/* was PGCLIENTENCODING set on
* startup? */
* startup? */
Oid
lastOid
;
/* saves oid from insert command
because people want it so badly */
char
*
progname
;
/* in case you renamed psql */
char
*
progname
;
/* in case you renamed psql */
}
PsqlSettings
;
}
PsqlSettings
;
extern
PsqlSettings
pset
;
#define QUIET() (GetVariableBool(pset.vars, "QUIET"))
#ifndef EXIT_SUCCESS
#ifndef EXIT_SUCCESS
...
...
src/bin/psql/startup.c
View file @
7c9390ca
#include <config.h>
#include <c.h>
#include <c.h>
#include <signal.h>
#include <signal.h>
...
@@ -34,10 +33,10 @@
...
@@ -34,10 +33,10 @@
#include "print.h"
#include "print.h"
#include "describe.h"
#include "describe.h"
PsqlSettings
pset
;
static
void
static
void
process_psqlrc
(
PsqlSettings
*
pset
);
process_psqlrc
(
void
);
static
void
static
void
showVersion
(
void
);
showVersion
(
void
);
...
@@ -67,7 +66,7 @@ struct adhoc_opts
...
@@ -67,7 +66,7 @@ struct adhoc_opts
};
};
static
void
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
...
@@ -79,7 +78,6 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
int
int
main
(
int
argc
,
char
**
argv
)
main
(
int
argc
,
char
**
argv
)
{
{
PsqlSettings
settings
;
struct
adhoc_opts
options
;
struct
adhoc_opts
options
;
int
successResult
;
int
successResult
;
...
@@ -87,64 +85,65 @@ main(int argc, char **argv)
...
@@ -87,64 +85,65 @@ main(int argc, char **argv)
char
*
password
=
NULL
;
char
*
password
=
NULL
;
bool
need_pass
;
bool
need_pass
;
memset
(
&
settings
,
0
,
sizeof
settings
);
memset
(
&
pset
,
0
,
sizeof
pset
);
if
(
!
strrchr
(
argv
[
0
],
SEP_CHAR
))
if
(
!
strrchr
(
argv
[
0
],
SEP_CHAR
))
settings
.
progname
=
argv
[
0
];
pset
.
progname
=
argv
[
0
];
else
else
settings
.
progname
=
strrchr
(
argv
[
0
],
SEP_CHAR
)
+
1
;
pset
.
progname
=
strrchr
(
argv
[
0
],
SEP_CHAR
)
+
1
;
settings
.
cur_cmd_source
=
stdin
;
pset
.
cur_cmd_source
=
stdin
;
settings
.
cur_cmd_interactive
=
false
;
pset
.
cur_cmd_interactive
=
false
;
settings
.
vars
=
CreateVariableSpace
();
pset
.
vars
=
CreateVariableSpace
();
settings
.
popt
.
topt
.
format
=
PRINT_ALIGNED
;
pset
.
popt
.
topt
.
format
=
PRINT_ALIGNED
;
settings
.
queryFout
=
stdout
;
pset
.
queryFout
=
stdout
;
settings
.
popt
.
topt
.
fieldSep
=
strdup
(
DEFAULT_FIELD_SEP
);
pset
.
popt
.
topt
.
fieldSep
=
strdup
(
DEFAULT_FIELD_SEP
);
settings
.
popt
.
topt
.
border
=
1
;
pset
.
popt
.
topt
.
border
=
1
;
settings
.
popt
.
topt
.
pager
=
1
;
pset
.
popt
.
topt
.
pager
=
1
;
SetVariable
(
settings
.
vars
,
"prompt1"
,
DEFAULT_PROMPT1
);
SetVariable
(
pset
.
vars
,
"PROMPT1"
,
DEFAULT_PROMPT1
);
SetVariable
(
settings
.
vars
,
"prompt2"
,
DEFAULT_PROMPT2
);
SetVariable
(
pset
.
vars
,
"PROMPT2"
,
DEFAULT_PROMPT2
);
SetVariable
(
settings
.
vars
,
"prompt3"
,
DEFAULT_PROMPT3
);
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. */
/* This is obsolete and will be removed very soon. */
#ifdef PSQL_ALWAYS_GET_PASSWORDS
#ifdef PSQL_ALWAYS_GET_PASSWORDS
settings
.
getPassword
=
true
;
pset
.
getPassword
=
true
;
#else
#else
settings
.
getPassword
=
false
;
pset
.
getPassword
=
false
;
#endif
#endif
#ifdef MULTIBYTE
#ifdef MULTIBYTE
settings
.
has_client_encoding
=
(
getenv
(
"PGCLIENTENCODING"
)
!=
NULL
);
pset
.
has_client_encoding
=
(
getenv
(
"PGCLIENTENCODING"
)
!=
NULL
);
#endif
#endif
parse_options
(
argc
,
argv
,
&
settings
,
&
options
);
parse_options
(
argc
,
argv
,
&
options
);
if
(
options
.
action
==
ACT_LIST_DB
)
if
(
options
.
action
==
ACT_LIST_DB
)
options
.
dbname
=
"template1"
;
options
.
dbname
=
"template1"
;
if
(
options
.
username
)
if
(
options
.
username
)
{
{
if
(
strcmp
(
options
.
username
,
"
?
"
)
==
0
)
if
(
strcmp
(
options
.
username
,
"
\001
"
)
==
0
)
username
=
simple_prompt
(
"Username: "
,
100
,
true
);
username
=
simple_prompt
(
"Username: "
,
100
,
true
);
else
else
username
=
strdup
(
options
.
username
);
username
=
strdup
(
options
.
username
);
}
}
if
(
settings
.
getPassword
)
if
(
pset
.
getPassword
)
password
=
simple_prompt
(
"Password: "
,
100
,
false
);
password
=
simple_prompt
(
"Password: "
,
100
,
false
);
/* loop until we have a password if requested by backend */
/* loop until we have a password if requested by backend */
do
do
{
{
need_pass
=
false
;
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
&&
if
(
PQstatus
(
pset
.
db
)
==
CONNECTION_BAD
&&
strcmp
(
PQerrorMessage
(
settings
.
db
),
"fe_sendauth: no password supplied
\n
"
)
==
0
)
strcmp
(
PQerrorMessage
(
pset
.
db
),
"fe_sendauth: no password supplied
\n
"
)
==
0
)
{
{
need_pass
=
true
;
need_pass
=
true
;
free
(
password
);
free
(
password
);
...
@@ -156,58 +155,61 @@ main(int argc, char **argv)
...
@@ -156,58 +155,61 @@ main(int argc, char **argv)
free
(
username
);
free
(
username
);
free
(
password
);
free
(
password
);
if
(
PQstatus
(
settings
.
db
)
==
CONNECTION_BAD
)
if
(
PQstatus
(
pset
.
db
)
==
CONNECTION_BAD
)
{
{
fprintf
(
stderr
,
"%s: connection to database '%s' failed.
\n
%s"
,
fprintf
(
stderr
,
"%s: connection to database '%s' failed - %s"
,
settings
.
progname
,
PQdb
(
settings
.
db
),
pset
.
progname
,
PQdb
(
pset
.
db
),
PQerrorMessage
(
pset
.
db
));
PQerrorMessage
(
settings
.
db
));
PQfinish
(
pset
.
db
);
PQfinish
(
settings
.
db
);
exit
(
EXIT_BADCONN
);
exit
(
EXIT_BADCONN
);
}
}
if
(
options
.
action
==
ACT_LIST_DB
)
if
(
options
.
action
==
ACT_LIST_DB
)
{
{
int
success
=
listAllDbs
(
&
settings
,
false
);
int
success
=
listAllDbs
(
false
);
PQfinish
(
settings
.
db
);
PQfinish
(
pset
.
db
);
exit
(
!
success
);
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
"
printf
(
"Welcome to %s, the PostgreSQL interactive terminal.
\n\n
"
"Type:
\\
copyright for distribution terms
\n
"
"Type:
\\
copyright for distribution terms
\n
"
"
\\
h for help with SQL commands
\n
"
"
\\
h for help with SQL commands
\n
"
"
\\
? for help on internal slash commands
\n
"
"
\\
? for help on internal slash commands
\n
"
"
\\
g or terminate with semicolon to execute query
\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 */
/* Now find something to do */
/* process file given by -f */
/* process file given by -f */
if
(
options
.
action
==
ACT_FILE
)
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 */
/* process slash command if one was given to -c */
else
if
(
options
.
action
==
ACT_SINGLE_SLASH
)
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 */
/* If the query given to -c was a normal one, send it */
else
if
(
options
.
action
==
ACT_SINGLE_QUERY
)
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 */
/* or otherwise enter interactive main loop */
else
else
successResult
=
MainLoop
(
&
settings
,
stdin
);
{
process_psqlrc
();
initializeInput
(
options
.
no_readline
?
0
:
1
);
successResult
=
MainLoop
(
stdin
);
finishInput
();
}
/* clean up */
/* clean up */
finishInput
();
PQfinish
(
pset
.
db
);
PQfinish
(
settings
.
db
);
setQFout
(
NULL
);
setQFout
(
NULL
,
&
settings
);
DestroyVariableSpace
(
pset
.
vars
);
DestroyVariableSpace
(
settings
.
vars
);
return
successResult
;
return
successResult
;
}
}
...
@@ -225,7 +227,7 @@ int getopt(int, char *const[], const char *);
...
@@ -225,7 +227,7 @@ int getopt(int, char *const[], const char *);
#endif
#endif
static
void
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
#ifdef HAVE_GETOPT_LONG
static
struct
option
long_options
[]
=
{
static
struct
option
long_options
[]
=
{
...
@@ -234,9 +236,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
...
@@ -234,9 +236,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
{
"database"
,
required_argument
,
NULL
,
'd'
},
{
"database"
,
required_argument
,
NULL
,
'd'
},
{
"dbname"
,
required_argument
,
NULL
,
'd'
},
{
"dbname"
,
required_argument
,
NULL
,
'd'
},
{
"echo"
,
no_argument
,
NULL
,
'e'
},
{
"echo"
,
no_argument
,
NULL
,
'e'
},
{
"echo-queries"
,
no_argument
,
NULL
,
'e'
},
{
"echo-hidden"
,
no_argument
,
NULL
,
'E'
},
{
"echo-all"
,
no_argument
,
NULL
,
'E'
},
{
"echo-all-queries"
,
no_argument
,
NULL
,
'E'
},
{
"file"
,
required_argument
,
NULL
,
'f'
},
{
"file"
,
required_argument
,
NULL
,
'f'
},
{
"field-separator"
,
required_argument
,
NULL
,
'F'
},
{
"field-separator"
,
required_argument
,
NULL
,
'F'
},
{
"host"
,
required_argument
,
NULL
,
'h'
},
{
"host"
,
required_argument
,
NULL
,
'h'
},
...
@@ -261,12 +261,12 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
...
@@ -261,12 +261,12 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
};
};
int
optindex
;
int
optindex
;
#endif
#endif
extern
char
*
optarg
;
extern
char
*
optarg
;
extern
int
optind
;
extern
int
optind
;
int
c
;
int
c
;
bool
used_old_u_option
=
false
;
memset
(
options
,
0
,
sizeof
*
options
);
memset
(
options
,
0
,
sizeof
*
options
);
...
@@ -284,7 +284,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
...
@@ -284,7 +284,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
switch
(
c
)
switch
(
c
)
{
{
case
'A'
:
case
'A'
:
pset
->
popt
.
topt
.
format
=
PRINT_UNALIGNED
;
pset
.
popt
.
topt
.
format
=
PRINT_UNALIGNED
;
break
;
break
;
case
'c'
:
case
'c'
:
options
->
action_string
=
optarg
;
options
->
action_string
=
optarg
;
...
@@ -297,23 +297,23 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
...
@@ -297,23 +297,23 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
options
->
dbname
=
optarg
;
options
->
dbname
=
optarg
;
break
;
break
;
case
'e'
:
case
'e'
:
SetVariable
(
pset
->
vars
,
"echo"
,
"
"
);
SetVariable
(
pset
.
vars
,
"ECHO"
,
"full
"
);
break
;
break
;
case
'E'
:
case
'E'
:
SetVariable
(
pset
->
vars
,
"echo_secret
"
,
""
);
SetVariable
(
pset
.
vars
,
"ECHO_HIDDEN
"
,
""
);
break
;
break
;
case
'f'
:
case
'f'
:
options
->
action
=
ACT_FILE
;
options
->
action
=
ACT_FILE
;
options
->
action_string
=
optarg
;
options
->
action_string
=
optarg
;
break
;
break
;
case
'F'
:
case
'F'
:
pset
->
popt
.
topt
.
fieldSep
=
strdup
(
optarg
);
pset
.
popt
.
topt
.
fieldSep
=
strdup
(
optarg
);
break
;
break
;
case
'h'
:
case
'h'
:
options
->
host
=
optarg
;
options
->
host
=
optarg
;
break
;
break
;
case
'H'
:
case
'H'
:
pset
->
popt
.
topt
.
format
=
PRINT_HTML
;
pset
.
popt
.
topt
.
format
=
PRINT_HTML
;
break
;
break
;
case
'l'
:
case
'l'
:
options
->
action
=
ACT_LIST_DB
;
options
->
action
=
ACT_LIST_DB
;
...
@@ -322,7 +322,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
...
@@ -322,7 +322,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
options
->
no_readline
=
true
;
options
->
no_readline
=
true
;
break
;
break
;
case
'o'
:
case
'o'
:
setQFout
(
optarg
,
pset
);
setQFout
(
optarg
);
break
;
break
;
case
'p'
:
case
'p'
:
options
->
port
=
optarg
;
options
->
port
=
optarg
;
...
@@ -336,16 +336,16 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
...
@@ -336,16 +336,16 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
value
=
xstrdup
(
optarg
);
value
=
xstrdup
(
optarg
);
equal_loc
=
strchr
(
value
,
'='
);
equal_loc
=
strchr
(
value
,
'='
);
if
(
!
equal_loc
)
if
(
!
equal_loc
)
result
=
do_pset
(
value
,
NULL
,
&
pset
->
popt
,
true
);
result
=
do_pset
(
value
,
NULL
,
&
pset
.
popt
,
true
);
else
else
{
{
*
equal_loc
=
'\0'
;
*
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
)
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
);
exit
(
EXIT_FAILURE
);
}
}
...
@@ -353,29 +353,31 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
...
@@ -353,29 +353,31 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
break
;
break
;
}
}
case
'q'
:
case
'q'
:
SetVariable
(
pset
->
vars
,
"quiet
"
,
""
);
SetVariable
(
pset
.
vars
,
"QUIET
"
,
""
);
break
;
break
;
case
's'
:
case
's'
:
SetVariable
(
pset
->
vars
,
"singlestep
"
,
""
);
SetVariable
(
pset
.
vars
,
"SINGLESTEP
"
,
""
);
break
;
break
;
case
'S'
:
case
'S'
:
SetVariable
(
pset
->
vars
,
"singleline
"
,
""
);
SetVariable
(
pset
.
vars
,
"SINGLELINE
"
,
""
);
break
;
break
;
case
't'
:
case
't'
:
pset
->
popt
.
topt
.
tuples_only
=
true
;
pset
.
popt
.
topt
.
tuples_only
=
true
;
break
;
break
;
case
'T'
:
case
'T'
:
pset
->
popt
.
topt
.
tableAttr
=
xstrdup
(
optarg
);
pset
.
popt
.
topt
.
tableAttr
=
xstrdup
(
optarg
);
break
;
break
;
case
'u'
:
case
'u'
:
pset
->
getPassword
=
true
;
pset
.
getPassword
=
true
;
options
->
username
=
"?"
;
options
->
username
=
"
\001
"
;
/* hopefully nobody has that username */
/* this option is out */
used_old_u_option
=
true
;
break
;
break
;
case
'U'
:
case
'U'
:
options
->
username
=
optarg
;
options
->
username
=
optarg
;
break
;
break
;
case
'x'
:
case
'x'
:
pset
->
popt
.
topt
.
expanded
=
true
;
pset
.
popt
.
topt
.
expanded
=
true
;
break
;
break
;
case
'v'
:
case
'v'
:
{
{
...
@@ -386,20 +388,20 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
...
@@ -386,20 +388,20 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
equal_loc
=
strchr
(
value
,
'='
);
equal_loc
=
strchr
(
value
,
'='
);
if
(
!
equal_loc
)
if
(
!
equal_loc
)
{
{
if
(
!
DeleteVariable
(
pset
->
vars
,
value
))
if
(
!
DeleteVariable
(
pset
.
vars
,
value
))
{
{
fprintf
(
stderr
,
"%s: could not delete variable %s
\n
"
,
fprintf
(
stderr
,
"%s: could not delete variable %s
\n
"
,
pset
->
progname
,
value
);
pset
.
progname
,
value
);
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
}
}
else
else
{
{
*
equal_loc
=
'\0'
;
*
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
"
,
fprintf
(
stderr
,
"%s:
could not set variable
%s
\n
"
,
pset
->
progname
,
value
,
equal_loc
);
pset
.
progname
,
value
);
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
}
}
...
@@ -411,7 +413,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
...
@@ -411,7 +413,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
showVersion
();
showVersion
();
exit
(
EXIT_SUCCESS
);
exit
(
EXIT_SUCCESS
);
case
'W'
:
case
'W'
:
pset
->
getPassword
=
true
;
pset
.
getPassword
=
true
;
break
;
break
;
case
'?'
:
case
'?'
:
usage
();
usage
();
...
@@ -420,7 +422,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
...
@@ -420,7 +422,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
#ifndef HAVE_GETOPT_LONG
#ifndef HAVE_GETOPT_LONG
case
'-'
:
case
'-'
:
fprintf
(
stderr
,
"%s was compiled without support for long options.
\n
"
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
);
exit
(
EXIT_FAILURE
);
break
;
break
;
#endif
#endif
...
@@ -441,12 +443,16 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
...
@@ -441,12 +443,16 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
options
->
dbname
=
argv
[
optind
];
options
->
dbname
=
argv
[
optind
];
else
if
(
!
options
->
username
)
else
if
(
!
options
->
username
)
options
->
username
=
argv
[
optind
];
options
->
username
=
argv
[
optind
];
else
else
if
(
!
QUIET
())
fprintf
(
stderr
,
"%s: warning: extra option %s ignored
\n
"
,
fprintf
(
stderr
,
"%s: warning: extra option %s ignored
\n
"
,
pset
->
progname
,
argv
[
optind
]);
pset
.
progname
,
argv
[
optind
]);
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
...
@@ -455,7 +461,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
* Load /etc/psqlrc or .psqlrc file, if found.
* Load /etc/psqlrc or .psqlrc file, if found.
*/
*/
static
void
static
void
process_psqlrc
(
PsqlSettings
*
pset
)
process_psqlrc
(
void
)
{
{
char
*
psqlrc
;
char
*
psqlrc
;
char
*
home
;
char
*
home
;
...
@@ -466,9 +472,9 @@ process_psqlrc(PsqlSettings *pset)
...
@@ -466,9 +472,9 @@ process_psqlrc(PsqlSettings *pset)
/* System-wide startup file */
/* System-wide startup file */
if
(
access
(
"/etc/psqlrc-"
PG_RELEASE
"."
PG_VERSION
"."
PG_SUBVERSION
,
R_OK
)
==
0
)
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
)
else
if
(
access
(
"/etc/psqlrc"
,
R_OK
)
==
0
)
process_file
(
"/etc/psqlrc"
,
pset
);
process_file
(
"/etc/psqlrc"
);
/* Look for one in the home dir */
/* Look for one in the home dir */
home
=
getenv
(
"HOME"
);
home
=
getenv
(
"HOME"
);
...
@@ -484,12 +490,12 @@ process_psqlrc(PsqlSettings *pset)
...
@@ -484,12 +490,12 @@ process_psqlrc(PsqlSettings *pset)
sprintf
(
psqlrc
,
"%s/.psqlrc-"
PG_RELEASE
"."
PG_VERSION
"."
PG_SUBVERSION
,
home
);
sprintf
(
psqlrc
,
"%s/.psqlrc-"
PG_RELEASE
"."
PG_VERSION
"."
PG_SUBVERSION
,
home
);
if
(
access
(
psqlrc
,
R_OK
)
==
0
)
if
(
access
(
psqlrc
,
R_OK
)
==
0
)
process_file
(
psqlrc
,
pset
);
process_file
(
psqlrc
);
else
else
{
{
sprintf
(
psqlrc
,
"%s/.psqlrc"
,
home
);
sprintf
(
psqlrc
,
"%s/.psqlrc"
,
home
);
if
(
access
(
psqlrc
,
R_OK
)
==
0
)
if
(
access
(
psqlrc
,
R_OK
)
==
0
)
process_file
(
psqlrc
,
pset
);
process_file
(
psqlrc
);
}
}
free
(
psqlrc
);
free
(
psqlrc
);
}
}
...
@@ -529,7 +535,7 @@ showVersion(void)
...
@@ -529,7 +535,7 @@ showVersion(void)
#else
#else
#define _Feature
#define _Feature
#endif
#endif
fputs
(
"multibyte"
);
fputs
(
"multibyte"
,
stdout
);
#endif
#endif
#undef _Feature
#undef _Feature
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment