psql backslash commands are schema-aware. Pattern matching behavior
follows recent pghackers discussion. This commit includes all the relevant fixes from Greg Mullane's patch of 24-June.
This commit is contained in:
parent
6ce4a4e3e1
commit
039cb47988
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.26 2002/05/14 18:47:58 tgl Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.27 2002/08/10 03:56:23 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -249,16 +249,17 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Use <xref linkend="app-psql">'s <command>\z</command> command
|
Use <xref linkend="app-psql">'s <command>\dp</command> command
|
||||||
to obtain information about existing privileges, for example:
|
to obtain information about existing privileges, for example:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
lusitania=> \z mytable
|
lusitania=> \dp mytable
|
||||||
Access privileges for database "lusitania"
|
Access privileges for database "lusitania"
|
||||||
Table | Access privileges
|
Schema | Table | Access privileges
|
||||||
---------+---------------------------------------
|
--------+---------+---------------------------------------
|
||||||
mytable | {=r,miriam=arwdRxt,"group todos=arw"}
|
public | mytable | {=r,miriam=arwdRxt,"group todos=arw"}
|
||||||
|
(1 row)
|
||||||
</programlisting>
|
</programlisting>
|
||||||
The entries shown by <command>\z</command> are interpreted thus:
|
The entries shown by <command>\dp</command> are interpreted thus:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
=xxxx -- privileges granted to PUBLIC
|
=xxxx -- privileges granted to PUBLIC
|
||||||
uname=xxxx -- privileges granted to a user
|
uname=xxxx -- privileges granted to a user
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.69 2002/07/28 15:22:21 petere Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.70 2002/08/10 03:56:23 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -538,7 +538,7 @@ testdb=>
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To include whitespace into an argument you must quote it with a
|
To include whitespace into an argument you may quote it with a
|
||||||
single quote. To include a single quote into such an argument,
|
single quote. To include a single quote into such an argument,
|
||||||
precede it by a backslash. Anything contained in single quotes is
|
precede it by a backslash. Anything contained in single quotes is
|
||||||
furthermore subject to C-like substitutions for
|
furthermore subject to C-like substitutions for
|
||||||
@ -551,25 +551,24 @@ testdb=>
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
If an unquoted argument begins with a colon (<literal>:</literal>),
|
If an unquoted argument begins with a colon (<literal>:</literal>),
|
||||||
it is taken as a variable and the value of the variable is taken as
|
it is taken as a <application>psql</> variable and the value of the
|
||||||
the argument instead.
|
variable is used as the argument instead.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Arguments that are quoted in <quote>backticks</quote>
|
Arguments that are quoted in <quote>backticks</quote>
|
||||||
(<literal>`</literal>) are taken as a command line that is passed to
|
(<literal>`</literal>) are taken as a command line that is passed to
|
||||||
the shell. The output of the command (with a trailing newline
|
the shell. The output of the command (with any trailing newline
|
||||||
removed) is taken as the argument value. The above escape sequences
|
removed) is taken as the argument value. The above escape sequences
|
||||||
also apply in backticks.
|
also apply in backticks.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Some commands take the name of an <acronym>SQL</acronym> identifier
|
Some commands take an <acronym>SQL</acronym> identifier
|
||||||
(such as a table name) as argument. These arguments follow the
|
(such as a table name) as argument. These arguments follow the
|
||||||
syntax rules of <acronym>SQL</acronym> regarding double quotes: an
|
syntax rules of <acronym>SQL</acronym> regarding double quotes: an
|
||||||
identifier without double quotes is coerced to lower-case. For all
|
identifier without double quotes is coerced to lower-case, while
|
||||||
other commands double quotes are not special and will become part of
|
whitespace within double quotes is included in the argument.
|
||||||
the argument.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -732,18 +731,17 @@ testdb=>
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><literal>\d</literal> <replaceable class="parameter">relation</replaceable> </term>
|
<term><literal>\d</literal> [ <replaceable class="parameter">pattern</replaceable> ]</term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Shows all columns of <replaceable
|
For each relation (table, view, index, or sequence) matching the
|
||||||
class="parameter">relation</replaceable> (which could be a
|
<replaceable class="parameter">pattern</replaceable>, show all
|
||||||
table, view, index, or sequence), their types, and any special
|
columns, their types, and any special
|
||||||
attributes such as <literal>NOT NULL</literal> or defaults, if
|
attributes such as <literal>NOT NULL</literal> or defaults, if
|
||||||
any. If the relation is, in fact, a table, any defined indices,
|
any. Associated indexes, constraints, rules, and triggers are
|
||||||
primary keys, unique constraints and check constraints are also
|
also shown, as is the view definition if the relation is a view.
|
||||||
listed. If the relation is a view, the view definition is also
|
(<quote>Matching the pattern</> is defined below.)
|
||||||
shown.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -753,7 +751,8 @@ testdb=>
|
|||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
If <command>\d</command> is called without any arguments, it is
|
If <command>\d</command> is used without a
|
||||||
|
<replaceable class="parameter">pattern</replaceable> argument, it is
|
||||||
equivalent to <command>\dtvs</command> which will show a list of
|
equivalent to <command>\dtvs</command> which will show a list of
|
||||||
all tables, views, and sequences. This is purely a convenience
|
all tables, views, and sequences. This is purely a convenience
|
||||||
measure.
|
measure.
|
||||||
@ -776,34 +775,35 @@ testdb=>
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><literal>\dd</literal> [ <replaceable class="parameter">object</replaceable> ]</term>
|
<term><literal>\dd</literal> [ <replaceable class="parameter">pattern</replaceable> ]</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Shows the descriptions of <replaceable
|
Shows the descriptions of objects matching the <replaceable
|
||||||
class="parameter">object</replaceable> (which can be a regular
|
class="parameter">pattern</replaceable>, or of all visible objects if
|
||||||
expression), or of all objects if no argument is given.
|
no argument is given. But in either case, only objects that have
|
||||||
|
a description are listed.
|
||||||
(<quote>Object</quote> covers aggregates, functions, operators,
|
(<quote>Object</quote> covers aggregates, functions, operators,
|
||||||
types, relations (tables, views, indexes, sequences, large
|
types, relations (tables, views, indexes, sequences, large
|
||||||
objects), rules, and triggers.) For example:
|
objects), rules, and triggers.) For example:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
=> <userinput>\dd version</userinput>
|
=> <userinput>\dd version</userinput>
|
||||||
Object descriptions
|
Object descriptions
|
||||||
Name | What | Description
|
Schema | Name | Object | Description
|
||||||
---------+----------+---------------------------
|
------------+---------+----------+---------------------------
|
||||||
version | function | PostgreSQL version string
|
pg_catalog | version | function | PostgreSQL version string
|
||||||
(1 row)
|
(1 row)
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Descriptions for objects can be generated with the
|
Descriptions for objects can be created with the
|
||||||
<command>COMMENT ON</command> <acronym>SQL</acronym> command.
|
<command>COMMENT ON</command> <acronym>SQL</acronym> command.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
<productname>PostgreSQL</productname> stores the object
|
<productname>PostgreSQL</productname> stores the object
|
||||||
descriptions in the pg_description system table.
|
descriptions in the <structname>pg_description</> system table.
|
||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
@ -816,7 +816,7 @@ testdb=>
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Lists all available domains (derived types). If <replaceable
|
Lists all available domains (derived types). If <replaceable
|
||||||
class="parameter">pattern</replaceable> (a regular expression)
|
class="parameter">pattern</replaceable>
|
||||||
is specified, only matching domains are shown.
|
is specified, only matching domains are shown.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
@ -830,7 +830,7 @@ testdb=>
|
|||||||
<para>
|
<para>
|
||||||
Lists available functions, together with their argument and
|
Lists available functions, together with their argument and
|
||||||
return types. If <replaceable
|
return types. If <replaceable
|
||||||
class="parameter">pattern</replaceable> (a regular expression)
|
class="parameter">pattern</replaceable>
|
||||||
is specified, only matching functions are shown. If the form
|
is specified, only matching functions are shown. If the form
|
||||||
<literal>\df+</literal> is used, additional information about
|
<literal>\df+</literal> is used, additional information about
|
||||||
each function, including language and description, is shown.
|
each function, including language and description, is shown.
|
||||||
@ -844,18 +844,17 @@ testdb=>
|
|||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This is not the actual command name: The letters i, s, t, v, S
|
This is not the actual command name: the letters i, s, t, v, S
|
||||||
stand for index, sequence, table, view, and system table,
|
stand for index, sequence, table, view, and system table,
|
||||||
respectively. You can specify any or all of them in any order to
|
respectively. You can specify any or all of these letters, in any
|
||||||
obtain a listing of them, together with who the owner is.
|
order, to obtain a listing of all the matching objects.
|
||||||
|
If <quote>+</quote> is appended to the command name, each object is
|
||||||
|
listed with its associated description, if any.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If <replaceable class="parameter">pattern</replaceable> is
|
If a <replaceable class="parameter">pattern</replaceable> is
|
||||||
specified, it is a regular expression that restricts the listing
|
specified, only objects whose name matches the pattern are listed.
|
||||||
to those objects whose name matches. If one appends a
|
|
||||||
<quote>+</quote> to the command name, each object is listed with
|
|
||||||
its associated description, if any.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -873,12 +872,12 @@ testdb=>
|
|||||||
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><literal>\do [ <replaceable class="parameter">name</replaceable> ]</literal></term>
|
<term><literal>\do [ <replaceable class="parameter">pattern</replaceable> ]</literal></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Lists available operators with their operand and return types.
|
Lists available operators with their operand and return types.
|
||||||
If <replaceable class="parameter">name</replaceable> is
|
If a <replaceable class="parameter">pattern</replaceable> is
|
||||||
specified, only operators with that name will be shown.
|
specified, only operators whose name matches the pattern are listed.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -888,9 +887,17 @@ testdb=>
|
|||||||
<term><literal>\dp</literal> [ <replaceable class="parameter">pattern</replaceable> ]</term>
|
<term><literal>\dp</literal> [ <replaceable class="parameter">pattern</replaceable> ]</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This is an alias for <command>\z</command> which was included
|
Produces a list of all available tables with their
|
||||||
for its greater mnemonic value (<quote>display
|
associated access permissions.
|
||||||
permissions</quote>).
|
If a <replaceable class="parameter">pattern</replaceable> is
|
||||||
|
specified, only tables whose name matches the pattern are listed.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The commands <xref linkend="SQL-GRANT"> and
|
||||||
|
<xref linkend="SQL-REVOKE">
|
||||||
|
are used to set access permissions. See <xref linkend="SQL-GRANT">
|
||||||
|
for more information.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -912,7 +919,7 @@ testdb=>
|
|||||||
<term><literal>\du [ <replaceable class="parameter">pattern</replaceable> ]</literal></term>
|
<term><literal>\du [ <replaceable class="parameter">pattern</replaceable> ]</literal></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Lists all configured users or only those that match <replaceable
|
Lists all database users, or only those that match <replaceable
|
||||||
class="parameter">pattern</replaceable>.
|
class="parameter">pattern</replaceable>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
@ -1608,57 +1615,23 @@ lo_import 152801
|
|||||||
<term><literal>\z</literal> [ <replaceable class="parameter">pattern</replaceable> ]</term>
|
<term><literal>\z</literal> [ <replaceable class="parameter">pattern</replaceable> ]</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Produces a list of all tables in the database with their
|
Produces a list of all available tables with their
|
||||||
appropriate access permissions listed. If an argument is given
|
associated access permissions.
|
||||||
it is taken as a regular expression which limits the listing to
|
If a <replaceable class="parameter">pattern</replaceable> is
|
||||||
those tables which match it.
|
specified, only tables whose name matches the pattern are listed.
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
test=> <userinput>\z</userinput>
|
|
||||||
Access permissions for database "test"
|
|
||||||
Relation | Access permissions
|
|
||||||
----------+-------------------------------------
|
|
||||||
my_table | {"=r","joe=arwR", "group staff=ar"}
|
|
||||||
(1 row )
|
|
||||||
</programlisting>
|
|
||||||
Read this as follows:
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<literal>"=r"</literal>: <literal>PUBLIC</literal> has read
|
|
||||||
(<command>SELECT</command>) permission on the table.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<literal>"joe=arwR"</literal>: User <literal>joe</literal> has
|
|
||||||
read, write (<command>UPDATE</command>,
|
|
||||||
<command>DELETE</command>), <quote>append</quote>
|
|
||||||
(<command>INSERT</command>) permissions, and permission to
|
|
||||||
create rules on the table.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<literal>"group staff=ar"</literal>: Group
|
|
||||||
<literal>staff</literal> has <command>SELECT</command> and
|
|
||||||
<command>INSERT</command> permission.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The commands <xref linkend="SQL-GRANT"> and
|
The commands <xref linkend="SQL-GRANT"> and
|
||||||
<xref linkend="SQL-REVOKE">
|
<xref linkend="SQL-REVOKE">
|
||||||
are used to set access permissions.
|
are used to set access permissions. See <xref linkend="SQL-GRANT">
|
||||||
|
for more information.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This is an alias for <command>\dp</command> (<quote>display
|
||||||
|
permissions</quote>).
|
||||||
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
@ -1688,6 +1661,46 @@ Access permissions for database "test"
|
|||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The various <literal>\d</> commands accept a <replaceable
|
||||||
|
class="parameter">pattern</replaceable> parameter to specify the
|
||||||
|
object name(s) to be displayed. Patterns are interpreted similarly
|
||||||
|
to SQL identifiers, in that unquoted letters are forced to lowercase,
|
||||||
|
while double quotes (<literal>"</>) protect letters from case conversion
|
||||||
|
and allow incorporation of whitespace into the identifier. Within
|
||||||
|
double quotes, paired double quotes reduce to a single double quote in
|
||||||
|
the resulting name. For example, <literal>FOO"BAR"BAZ</> is interpreted
|
||||||
|
as <literal>fooBARbaz</>, and <literal>"A weird"" name"</> becomes
|
||||||
|
<literal>A weird" name</>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
More interestingly, <literal>\d</> patterns allow the use of
|
||||||
|
<literal>*</> to mean <quote>any sequence of characters</>, and
|
||||||
|
<literal>?</> to mean <quote>any single character</>. (This notation
|
||||||
|
is comparable to Unix shell filename patterns.) Advanced users can
|
||||||
|
also use regular-expression notations such as character classes, for
|
||||||
|
example <literal>[0-9]</> to match <quote>any digit</>. To make any of
|
||||||
|
these pattern-matching characters be interpreted literally, surround it
|
||||||
|
with double quotes.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
A pattern that contains an (unquoted) dot is interpreted as a schema
|
||||||
|
name pattern followed by an object name pattern. For example,
|
||||||
|
<literal> \dt foo*.bar*</> displays all tables in schemas whose name
|
||||||
|
starts with <literal>foo</> and whose table name
|
||||||
|
starts with <literal>bar</>. If no dot appears, then the pattern
|
||||||
|
matches only objects that are visible in the current schema search path.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Whenever the <replaceable class="parameter">pattern</replaceable> parameter
|
||||||
|
is omitted completely, the <literal>\d</> commands display all objects
|
||||||
|
that are visible in the current schema search path. To see all objects
|
||||||
|
in the database, use the pattern <literal>*.*</>.
|
||||||
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
|
|
||||||
<refsect2>
|
<refsect2>
|
||||||
@ -2402,11 +2415,12 @@ $ ./configure --with-includes=/opt/gnu/include --with-libs=/opt/gnu/lib ...
|
|||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
In some earlier life <application>psql</application> allowed the
|
In an earlier life <application>psql</application> allowed the
|
||||||
first argument to start directly after the (single-letter)
|
first argument of a single-letter backslash command to start
|
||||||
command. For compatibility this is still supported to some extent
|
directly after the command, without intervening whitespace. For
|
||||||
|
compatibility this is still supported to some extent,
|
||||||
but I am not going to explain the details here as this use is
|
but I am not going to explain the details here as this use is
|
||||||
discouraged. But if you get strange messages, keep this in mind.
|
discouraged. If you get strange messages, keep this in mind.
|
||||||
For example
|
For example
|
||||||
<programlisting>
|
<programlisting>
|
||||||
testdb=> <userinput>\foo</userinput>
|
testdb=> <userinput>\foo</userinput>
|
||||||
@ -2421,7 +2435,8 @@ Field separator is "oo",
|
|||||||
<application>psql</application> only works smoothly with servers
|
<application>psql</application> only works smoothly with servers
|
||||||
of the same version. That does not mean other combinations will
|
of the same version. That does not mean other combinations will
|
||||||
fail outright, but subtle and not-so-subtle problems might come
|
fail outright, but subtle and not-so-subtle problems might come
|
||||||
up.
|
up. Backslash commands are particularly likely to fail if the
|
||||||
|
server is of a different version.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* psql - the PostgreSQL interactive terminal
|
* psql - the PostgreSQL interactive terminal
|
||||||
*
|
*
|
||||||
* Copyright 2000 by PostgreSQL Global Development Group
|
* Copyright 2000-2002 by PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.74 2002/07/18 02:02:30 ishii Exp $
|
* $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.75 2002/08/10 03:56:23 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
@ -54,7 +54,7 @@ enum option_type
|
|||||||
OT_NORMAL, /* normal case */
|
OT_NORMAL, /* normal case */
|
||||||
OT_SQLID, /* treat as SQL identifier */
|
OT_SQLID, /* treat as SQL identifier */
|
||||||
OT_SQLIDHACK, /* SQL identifier, but don't downcase */
|
OT_SQLIDHACK, /* SQL identifier, but don't downcase */
|
||||||
OT_FILEPIPE /* it's a file or pipe */
|
OT_FILEPIPE /* it's a filename or pipe */
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *scan_option(char **string, enum option_type type,
|
static char *scan_option(char **string, enum option_type type,
|
||||||
@ -328,10 +328,11 @@ exec_command(const char *cmd,
|
|||||||
/* \d* commands */
|
/* \d* commands */
|
||||||
else if (cmd[0] == 'd')
|
else if (cmd[0] == 'd')
|
||||||
{
|
{
|
||||||
char *name;
|
char *pattern;
|
||||||
bool show_verbose;
|
bool show_verbose;
|
||||||
|
|
||||||
name = scan_option(&string, OT_SQLID, NULL, true);
|
/* We don't do SQLID reduction on the pattern yet */
|
||||||
|
pattern = scan_option(&string, OT_NORMAL, NULL, true);
|
||||||
|
|
||||||
show_verbose = strchr(cmd, '+') ? true : false;
|
show_verbose = strchr(cmd, '+') ? true : false;
|
||||||
|
|
||||||
@ -339,51 +340,53 @@ exec_command(const char *cmd,
|
|||||||
{
|
{
|
||||||
case '\0':
|
case '\0':
|
||||||
case '+':
|
case '+':
|
||||||
if (name)
|
if (pattern)
|
||||||
success = describeTableDetails(name, show_verbose);
|
success = describeTableDetails(pattern, show_verbose);
|
||||||
else
|
else
|
||||||
/* standard listing of interesting things */
|
/* standard listing of interesting things */
|
||||||
success = listTables("tvs", NULL, show_verbose);
|
success = listTables("tvs", NULL, show_verbose);
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
success = describeAggregates(name);
|
success = describeAggregates(pattern, show_verbose);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
success = objectDescription(name);
|
success = objectDescription(pattern);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
success = describeFunctions(name, show_verbose);
|
success = describeFunctions(pattern, show_verbose);
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
success = do_lo_list();
|
success = do_lo_list();
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
success = describeOperators(name);
|
success = describeOperators(pattern);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
success = permissionsList(name);
|
success = permissionsList(pattern);
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
success = describeTypes(name, show_verbose);
|
success = describeTypes(pattern, show_verbose);
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
case 'v':
|
case 'v':
|
||||||
case 'i':
|
case 'i':
|
||||||
case 's':
|
case 's':
|
||||||
case 'S':
|
case 'S':
|
||||||
success = listTables(&cmd[1], name, show_verbose);
|
success = listTables(&cmd[1], pattern, show_verbose);
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
success = describeUsers(name);
|
success = describeUsers(pattern);
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
success = listDomains(name);
|
success = listDomains(pattern);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
status = CMD_UNKNOWN;
|
status = CMD_UNKNOWN;
|
||||||
}
|
}
|
||||||
free(name);
|
|
||||||
|
if (pattern)
|
||||||
|
free(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -815,13 +818,14 @@ exec_command(const char *cmd,
|
|||||||
success = do_pset("expanded", NULL, &pset.popt, quiet);
|
success = do_pset("expanded", NULL, &pset.popt, quiet);
|
||||||
|
|
||||||
|
|
||||||
/* \z -- list table rights (grant/revoke) */
|
/* \z -- list table rights (equivalent to \dp) */
|
||||||
else if (strcmp(cmd, "z") == 0)
|
else if (strcmp(cmd, "z") == 0)
|
||||||
{
|
{
|
||||||
char *opt = scan_option(&string, OT_SQLID, NULL, true);
|
char *pattern = scan_option(&string, OT_NORMAL, NULL, true);
|
||||||
|
|
||||||
success = permissionsList(opt);
|
success = permissionsList(pattern);
|
||||||
free(opt);
|
if (pattern)
|
||||||
|
free(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \! -- shell escape */
|
/* \! -- shell escape */
|
||||||
@ -881,11 +885,27 @@ exec_command(const char *cmd,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* scan_option()
|
* scan_option()
|
||||||
|
*
|
||||||
|
* *string points to possible option string on entry; on exit, it's updated
|
||||||
|
* to point past the option string (if any).
|
||||||
|
*
|
||||||
|
* type tells what processing, if any, to perform on the option string;
|
||||||
|
* for example, if it's a SQL identifier, we want to downcase any unquoted
|
||||||
|
* letters.
|
||||||
|
*
|
||||||
|
* if quote is not NULL, *quote is set to 0 if no quoting was found, else
|
||||||
|
* the quote symbol.
|
||||||
|
*
|
||||||
|
* if semicolon is true, trailing semicolon(s) that would otherwise be taken
|
||||||
|
* as part of the option string will be stripped.
|
||||||
|
*
|
||||||
|
* Return value is NULL if no option found, else a malloc'd copy of the
|
||||||
|
* processed option value.
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
scan_option(char **string, enum option_type type, char *quote, bool semicolon)
|
scan_option(char **string, enum option_type type, char *quote, bool semicolon)
|
||||||
{
|
{
|
||||||
unsigned int pos = 0;
|
unsigned int pos;
|
||||||
char *options_string;
|
char *options_string;
|
||||||
char *return_val;
|
char *return_val;
|
||||||
|
|
||||||
@ -897,82 +917,27 @@ scan_option(char **string, enum option_type type, char *quote, bool semicolon)
|
|||||||
|
|
||||||
options_string = *string;
|
options_string = *string;
|
||||||
/* skip leading whitespace */
|
/* skip leading whitespace */
|
||||||
pos += strspn(options_string + pos, " \t\n\r");
|
pos = strspn(options_string, " \t\n\r");
|
||||||
|
|
||||||
switch (options_string[pos])
|
switch (options_string[pos])
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Double quoted string
|
* End of line: no option present
|
||||||
*/
|
*/
|
||||||
case '"':
|
case '\0':
|
||||||
{
|
*string = &options_string[pos];
|
||||||
unsigned int jj;
|
|
||||||
unsigned short int bslash_count = 0;
|
|
||||||
|
|
||||||
/* scan for end of quote */
|
|
||||||
for (jj = pos + 1; options_string[jj]; jj += PQmblen(&options_string[jj], pset.encoding))
|
|
||||||
{
|
|
||||||
if (options_string[jj] == '"' && bslash_count % 2 == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (options_string[jj] == '\\')
|
|
||||||
bslash_count++;
|
|
||||||
else
|
|
||||||
bslash_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options_string[jj] == 0)
|
|
||||||
{
|
|
||||||
psql_error("parse error at the end of line\n");
|
|
||||||
*string = &options_string[jj];
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
return_val = malloc(jj - pos + 2);
|
|
||||||
if (!return_val)
|
|
||||||
{
|
|
||||||
psql_error("out of memory\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is expected to be an SQL identifier like option
|
* Next command: treat like end of line
|
||||||
* then we strip out the double quotes
|
*
|
||||||
|
* XXX this means we can't conveniently accept options that
|
||||||
|
* start with a backslash; therefore, option processing that
|
||||||
|
* encourages use of backslashes is rather broken.
|
||||||
*/
|
*/
|
||||||
|
case '\\':
|
||||||
if (type == OT_SQLID || type == OT_SQLIDHACK)
|
*string = &options_string[pos];
|
||||||
{
|
return NULL;
|
||||||
unsigned int k,
|
|
||||||
cc;
|
|
||||||
|
|
||||||
bslash_count = 0;
|
|
||||||
cc = 0;
|
|
||||||
for (k = pos + 1; options_string[k]; k += PQmblen(&options_string[k], pset.encoding))
|
|
||||||
{
|
|
||||||
if (options_string[k] == '"' && bslash_count % 2 == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (options_string[jj] == '\\')
|
|
||||||
bslash_count++;
|
|
||||||
else
|
|
||||||
bslash_count = 0;
|
|
||||||
|
|
||||||
return_val[cc++] = options_string[k];
|
|
||||||
}
|
|
||||||
return_val[cc] = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strncpy(return_val, &options_string[pos], jj - pos + 1);
|
|
||||||
return_val[jj - pos + 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
*string = options_string + jj + 1;
|
|
||||||
if (quote)
|
|
||||||
*quote = '"';
|
|
||||||
|
|
||||||
return return_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A single quote has a psql internal meaning, such as for
|
* A single quote has a psql internal meaning, such as for
|
||||||
@ -1015,7 +980,7 @@ scan_option(char **string, enum option_type type, char *quote, bool semicolon)
|
|||||||
case '`':
|
case '`':
|
||||||
{
|
{
|
||||||
bool error = false;
|
bool error = false;
|
||||||
FILE *fd = NULL;
|
FILE *fd;
|
||||||
char *file;
|
char *file;
|
||||||
PQExpBufferData output;
|
PQExpBufferData output;
|
||||||
char buf[512];
|
char buf[512];
|
||||||
@ -1040,10 +1005,10 @@ scan_option(char **string, enum option_type type, char *quote, bool semicolon)
|
|||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error)
|
|
||||||
{
|
|
||||||
initPQExpBuffer(&output);
|
initPQExpBuffer(&output);
|
||||||
|
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
result = fread(buf, 1, 512, fd);
|
result = fread(buf, 1, 512, fd);
|
||||||
@ -1056,27 +1021,26 @@ scan_option(char **string, enum option_type type, char *quote, bool semicolon)
|
|||||||
appendBinaryPQExpBuffer(&output, buf, result);
|
appendBinaryPQExpBuffer(&output, buf, result);
|
||||||
} while (!feof(fd));
|
} while (!feof(fd));
|
||||||
appendPQExpBufferChar(&output, '\0');
|
appendPQExpBufferChar(&output, '\0');
|
||||||
|
}
|
||||||
|
|
||||||
if (pclose(fd) == -1)
|
if (fd && pclose(fd) == -1)
|
||||||
{
|
{
|
||||||
psql_error("%s: %s\n", file, strerror(errno));
|
psql_error("%s: %s\n", file, strerror(errno));
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
if (output.data[strlen(output.data) - 1] == '\n')
|
if (output.data[strlen(output.data) - 1] == '\n')
|
||||||
output.data[strlen(output.data) - 1] = '\0';
|
output.data[strlen(output.data) - 1] = '\0';
|
||||||
}
|
|
||||||
|
|
||||||
if (!error)
|
|
||||||
return_val = output.data;
|
return_val = output.data;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return_val = xstrdup("");
|
return_val = xstrdup("");
|
||||||
termPQExpBuffer(&output);
|
termPQExpBuffer(&output);
|
||||||
}
|
}
|
||||||
|
|
||||||
options_string[pos + 1 + len] = '`';
|
options_string[pos + 1 + len] = '`';
|
||||||
*string = options_string + pos + len + 2;
|
*string = options_string + pos + len + 2;
|
||||||
if (quote)
|
if (quote)
|
||||||
@ -1084,13 +1048,6 @@ scan_option(char **string, enum option_type type, char *quote, bool semicolon)
|
|||||||
return return_val;
|
return return_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* end of line
|
|
||||||
*/
|
|
||||||
case 0:
|
|
||||||
*string = &options_string[pos];
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Variable substitution
|
* Variable substitution
|
||||||
*/
|
*/
|
||||||
@ -1109,17 +1066,10 @@ scan_option(char **string, enum option_type type, char *quote, bool semicolon)
|
|||||||
return_val = xstrdup(value);
|
return_val = xstrdup(value);
|
||||||
options_string[pos + token_end + 1] = save_char;
|
options_string[pos + token_end + 1] = save_char;
|
||||||
*string = &options_string[pos + token_end + 1];
|
*string = &options_string[pos + token_end + 1];
|
||||||
|
/* XXX should we set *quote to ':' here? */
|
||||||
return return_val;
|
return return_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Next command
|
|
||||||
*/
|
|
||||||
case '\\':
|
|
||||||
*string = options_string + pos;
|
|
||||||
return NULL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* | could be the beginning of a pipe if so, take rest of line
|
* | could be the beginning of a pipe if so, take rest of line
|
||||||
* as command
|
* as command
|
||||||
@ -1127,49 +1077,135 @@ scan_option(char **string, enum option_type type, char *quote, bool semicolon)
|
|||||||
case '|':
|
case '|':
|
||||||
if (type == OT_FILEPIPE)
|
if (type == OT_FILEPIPE)
|
||||||
{
|
{
|
||||||
*string += strlen(options_string + pos);
|
*string += strlen(*string);
|
||||||
return xstrdup(options_string + pos);
|
return xstrdup(options_string + pos);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
/* fallthrough for other option types */
|
/* fallthrough for other option types */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A normal word
|
* Default case: token extends to next whitespace, except that
|
||||||
|
* whitespace within double quotes doesn't end the token.
|
||||||
|
*
|
||||||
|
* If we are processing the option as a SQL identifier, then
|
||||||
|
* downcase unquoted letters and remove double-quotes --- but
|
||||||
|
* doubled double-quotes become output double-quotes, per spec.
|
||||||
|
*
|
||||||
|
* Note that a string like FOO"BAR"BAZ will be converted to
|
||||||
|
* fooBARbaz; this is somewhat inconsistent with the SQL spec,
|
||||||
|
* which would have us parse it as several identifiers. But
|
||||||
|
* for psql's purposes, we want a string like "foo"."bar" to
|
||||||
|
* be treated as one option, so there's little choice.
|
||||||
*/
|
*/
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
size_t token_end;
|
bool inquotes = false;
|
||||||
|
size_t token_len;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
token_end = strcspn(&options_string[pos], " \t\n\r");
|
/* Find end of option */
|
||||||
return_val = malloc(token_end + 1);
|
|
||||||
|
cp = &options_string[pos];
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/* Find next quote, whitespace, or end of string */
|
||||||
|
cp += strcspn(cp, "\" \t\n\r");
|
||||||
|
if (inquotes)
|
||||||
|
{
|
||||||
|
if (*cp == '\0')
|
||||||
|
{
|
||||||
|
psql_error("parse error at the end of line\n");
|
||||||
|
*string = cp;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (*cp == '"')
|
||||||
|
inquotes = false;
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*cp != '"')
|
||||||
|
break; /* whitespace or end of string */
|
||||||
|
if (quote)
|
||||||
|
*quote = '"';
|
||||||
|
inquotes = true;
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*string = cp;
|
||||||
|
|
||||||
|
/* Copy the option */
|
||||||
|
token_len = cp - &options_string[pos];
|
||||||
|
|
||||||
|
return_val = malloc(token_len + 1);
|
||||||
if (!return_val)
|
if (!return_val)
|
||||||
{
|
{
|
||||||
psql_error("out of memory\n");
|
psql_error("out of memory\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
strncpy(return_val, &options_string[pos], token_end);
|
|
||||||
return_val[token_end] = 0;
|
|
||||||
|
|
||||||
/* Strip any trailing semi-colons for some types */
|
memcpy(return_val, &options_string[pos], token_len);
|
||||||
|
return_val[token_len] = '\0';
|
||||||
|
|
||||||
|
/* Strip any trailing semi-colons if requested */
|
||||||
if (semicolon)
|
if (semicolon)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = strlen(return_val) - 1; i && return_val[i] == ';'; i--);
|
for (i = token_len - 1;
|
||||||
if (i < strlen(return_val) - 1)
|
i >= 0 && return_val[i] == ';';
|
||||||
|
i--)
|
||||||
|
/* skip */;
|
||||||
|
|
||||||
|
if (i < 0)
|
||||||
|
{
|
||||||
|
/* nothing left after stripping the semicolon... */
|
||||||
|
free(return_val);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < token_len - 1)
|
||||||
return_val[i + 1] = '\0';
|
return_val[i + 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == OT_SQLID)
|
/*
|
||||||
for (cp = return_val; *cp; cp += PQmblen(cp, pset.encoding))
|
* If SQL identifier processing was requested,
|
||||||
|
* then we strip out excess double quotes and downcase
|
||||||
|
* unquoted letters.
|
||||||
|
*/
|
||||||
|
if (type == OT_SQLID || type == OT_SQLIDHACK)
|
||||||
|
{
|
||||||
|
inquotes = false;
|
||||||
|
cp = return_val;
|
||||||
|
|
||||||
|
while (*cp)
|
||||||
|
{
|
||||||
|
if (*cp == '"')
|
||||||
|
{
|
||||||
|
if (inquotes && cp[1] == '"')
|
||||||
|
{
|
||||||
|
/* Keep the first quote, remove the second */
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
inquotes = !inquotes;
|
||||||
|
/* Collapse out quote at *cp */
|
||||||
|
memmove(cp, cp+1, strlen(cp));
|
||||||
|
/* do not advance cp */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!inquotes && type == OT_SQLID)
|
||||||
|
{
|
||||||
if (isupper((unsigned char) *cp))
|
if (isupper((unsigned char) *cp))
|
||||||
*cp = tolower((unsigned char) *cp);
|
*cp = tolower((unsigned char) *cp);
|
||||||
|
}
|
||||||
*string = &options_string[pos + token_end];
|
cp += PQmblen(cp, pset.encoding);
|
||||||
return return_val;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return return_val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1429,7 +1465,7 @@ test_superuser(const char *username)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
initPQExpBuffer(&buf);
|
initPQExpBuffer(&buf);
|
||||||
printfPQExpBuffer(&buf, "SELECT usesuper FROM pg_user WHERE usename = '%s'", username);
|
printfPQExpBuffer(&buf, "SELECT usesuper FROM pg_catalog.pg_user WHERE usename = '%s'", username);
|
||||||
res = PSQLexec(buf.data);
|
res = PSQLexec(buf.data);
|
||||||
termPQExpBuffer(&buf);
|
termPQExpBuffer(&buf);
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* psql - the PostgreSQL interactive terminal
|
* psql - the PostgreSQL interactive terminal
|
||||||
*
|
*
|
||||||
* Copyright 2000 by PostgreSQL Global Development Group
|
* Copyright 2000-2002 by PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/bin/psql/describe.h,v 1.16 2002/03/19 02:32:21 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/bin/psql/describe.h,v 1.17 2002/08/10 03:56:24 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef DESCRIBE_H
|
#ifndef DESCRIBE_H
|
||||||
#define DESCRIBE_H
|
#define DESCRIBE_H
|
||||||
@ -11,36 +11,36 @@
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
/* \da */
|
/* \da */
|
||||||
bool describeAggregates(const char *name);
|
bool describeAggregates(const char *pattern, bool verbose);
|
||||||
|
|
||||||
/* \df */
|
/* \df */
|
||||||
bool describeFunctions(const char *name, bool verbose);
|
bool describeFunctions(const char *pattern, bool verbose);
|
||||||
|
|
||||||
/* \dT */
|
/* \dT */
|
||||||
bool describeTypes(const char *name, bool verbose);
|
bool describeTypes(const char *pattern, bool verbose);
|
||||||
|
|
||||||
/* \do */
|
/* \do */
|
||||||
bool describeOperators(const char *name);
|
bool describeOperators(const char *pattern);
|
||||||
|
|
||||||
/* \du */
|
/* \du */
|
||||||
bool describeUsers(const char *name);
|
bool describeUsers(const char *pattern);
|
||||||
|
|
||||||
/* \z (or \dp) */
|
/* \z (or \dp) */
|
||||||
bool permissionsList(const char *name);
|
bool permissionsList(const char *pattern);
|
||||||
|
|
||||||
/* \dd */
|
/* \dd */
|
||||||
bool objectDescription(const char *object);
|
bool objectDescription(const char *pattern);
|
||||||
|
|
||||||
/* \d foo */
|
/* \d foo */
|
||||||
bool describeTableDetails(const char *name, bool desc);
|
bool describeTableDetails(const char *pattern, bool verbose);
|
||||||
|
|
||||||
/* \l */
|
/* \l */
|
||||||
bool listAllDbs(bool desc);
|
bool listAllDbs(bool desc);
|
||||||
|
|
||||||
/* \dt, \di, \ds, \dS, etc. */
|
/* \dt, \di, \ds, \dS, etc. */
|
||||||
bool listTables(const char *infotype, const char *name, bool desc);
|
bool listTables(const char *tabtypes, const char *pattern, bool verbose);
|
||||||
|
|
||||||
/* \dD */
|
/* \dD */
|
||||||
bool listDomains(const char *name);
|
bool listDomains(const char *pattern);
|
||||||
|
|
||||||
#endif /* DESCRIBE_H */
|
#endif /* DESCRIBE_H */
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* psql - the PostgreSQL interactive terminal
|
* psql - the PostgreSQL interactive terminal
|
||||||
*
|
*
|
||||||
* Copyright 2000 by PostgreSQL Global Development Group
|
* Copyright 2000-2002 by PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.19 2002/03/06 06:10:31 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.20 2002/08/10 03:56:24 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "large_obj.h"
|
#include "large_obj.h"
|
||||||
@ -209,9 +209,10 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sprintf(cmdbuf,
|
sprintf(cmdbuf,
|
||||||
"INSERT INTO pg_description VALUES ('%u', "
|
"INSERT INTO pg_catalog.pg_description VALUES ('%u', "
|
||||||
"(SELECT oid FROM pg_class WHERE relname = 'pg_largeobject'),"
|
"'pg_catalog.pg_largeobject'::regclass, "
|
||||||
" 0, '", loid);
|
"0, '",
|
||||||
|
loid);
|
||||||
bufptr = cmdbuf + strlen(cmdbuf);
|
bufptr = cmdbuf + strlen(cmdbuf);
|
||||||
for (i = 0; i < slen; i++)
|
for (i = 0; i < slen; i++)
|
||||||
{
|
{
|
||||||
@ -310,8 +311,8 @@ do_lo_unlink(const char *loid_arg)
|
|||||||
/* XXX ought to replace this with some kind of COMMENT command */
|
/* XXX ought to replace this with some kind of COMMENT command */
|
||||||
if (pset.issuper)
|
if (pset.issuper)
|
||||||
{
|
{
|
||||||
sprintf(buf, "DELETE FROM pg_description WHERE objoid = '%u' "
|
sprintf(buf, "DELETE FROM pg_catalog.pg_description WHERE objoid = '%u' "
|
||||||
"AND classoid = (SELECT oid FROM pg_class WHERE relname = 'pg_largeobject')",
|
"AND classoid = 'pg_catalog.pg_largeobject'::regclass",
|
||||||
loid);
|
loid);
|
||||||
if (!(res = PSQLexec(buf)))
|
if (!(res = PSQLexec(buf)))
|
||||||
{
|
{
|
||||||
@ -356,8 +357,8 @@ do_lo_list(void)
|
|||||||
printQueryOpt myopt = pset.popt;
|
printQueryOpt myopt = pset.popt;
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
snprintf(buf, sizeof(buf),
|
||||||
"SELECT loid as \"ID\", obj_description(loid, 'pg_largeobject') as \"%s\"\n"
|
"SELECT loid as \"ID\", pg_catalog.obj_description(loid, 'pg_largeobject') as \"%s\"\n"
|
||||||
"FROM (SELECT DISTINCT loid FROM pg_largeobject) x\n"
|
"FROM (SELECT DISTINCT loid FROM pg_catalog.pg_largeobject) x\n"
|
||||||
"ORDER BY \"ID\"",
|
"ORDER BY \"ID\"",
|
||||||
gettext("Description"));
|
gettext("Description"));
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* psql - the PostgreSQL interactive terminal
|
* psql - the PostgreSQL interactive terminal
|
||||||
*
|
*
|
||||||
* Copyright 2000 by PostgreSQL Global Development Group
|
* Copyright 2000-2002 by PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.55 2002/08/04 05:01:57 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.56 2002/08/10 03:56:24 tgl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*----------------------------------------------------------------------
|
/*----------------------------------------------------------------------
|
||||||
@ -118,11 +118,20 @@ initialize_readline(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Queries to get lists of names of various kinds of things, possibly
|
||||||
|
* restricted to names matching a partially entered name. In these queries,
|
||||||
|
* the %s will be replaced by the text entered so far, the %d by its length.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define Query_for_list_of_tables "SELECT relname FROM pg_catalog.pg_class WHERE (relkind='r' or relkind='v') and substr(relname,1,%d)='%s' and pg_catalog.pg_table_is_visible(oid)"
|
||||||
|
#define Query_for_list_of_indexes "SELECT relname FROM pg_catalog.pg_class WHERE relkind='i' and substr(relname,1,%d)='%s' and pg_catalog.pg_table_is_visible(oid)"
|
||||||
|
#define Query_for_list_of_databases "SELECT datname FROM pg_catalog.pg_database WHERE substr(datname,1,%d)='%s'"
|
||||||
|
#define Query_for_list_of_attributes "SELECT a.attname FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c WHERE c.oid = a.attrelid and a.attnum>0 and not a.attisdropped and substr(a.attname,1,%d)='%s' and c.relname='%s' and pg_catalog.pg_table_is_visible(c.oid)"
|
||||||
|
#define Query_for_list_of_users "SELECT usename FROM pg_catalog.pg_user WHERE substr(usename,1,%d)='%s'"
|
||||||
|
|
||||||
/* This is a list of all "things" in Pgsql, which can show up after CREATE or
|
/* This is a list of all "things" in Pgsql, which can show up after CREATE or
|
||||||
DROP; and there is also a query to get a list of them.
|
DROP; and there is also a query to get a list of them.
|
||||||
The %s will be replaced by the text entered so far, the %d by its length.
|
|
||||||
If you change the order here or insert things, make sure to also adjust the
|
|
||||||
referencing macros below.
|
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -131,37 +140,29 @@ typedef struct
|
|||||||
} pgsql_thing_t;
|
} pgsql_thing_t;
|
||||||
|
|
||||||
pgsql_thing_t words_after_create[] = {
|
pgsql_thing_t words_after_create[] = {
|
||||||
{"AGGREGATE", "SELECT distinct proname FROM pg_catalog.pg_proc WHERE proisagg AND substr(proname,1,%d)='%s'"},
|
{"AGGREGATE", "SELECT DISTINCT proname FROM pg_catalog.pg_proc WHERE proisagg AND substr(proname,1,%d)='%s'"},
|
||||||
{"DATABASE", "SELECT datname FROM pg_catalog.pg_database WHERE substr(datname,1,%d)='%s'"},
|
{"DATABASE", Query_for_list_of_databases},
|
||||||
{"FUNCTION", "SELECT distinct proname FROM pg_catalog.pg_proc WHERE substr(proname,1,%d)='%s'"},
|
{"FUNCTION", "SELECT DISTINCT proname FROM pg_catalog.pg_proc WHERE substr(proname,1,%d)='%s'"},
|
||||||
{"GROUP", "SELECT groname FROM pg_catalog.pg_group WHERE substr(groname,1,%d)='%s'"},
|
{"GROUP", "SELECT groname FROM pg_catalog.pg_group WHERE substr(groname,1,%d)='%s'"},
|
||||||
{"INDEX", "SELECT relname FROM pg_catalog.pg_class WHERE relkind='i' and substr(relname,1,%d)='%s'"},
|
{"INDEX", Query_for_list_of_indexes},
|
||||||
{"OPERATOR", NULL}, /* Querying for this is probably not such a good idea. */
|
{"OPERATOR", NULL}, /* Querying for this is probably not such a good idea. */
|
||||||
{"RULE", "SELECT rulename FROM pg_catalog.pg_rules WHERE substr(rulename,1,%d)='%s'"},
|
{"RULE", "SELECT rulename FROM pg_catalog.pg_rules WHERE substr(rulename,1,%d)='%s'"},
|
||||||
{"SCHEMA", "SELECT nspname FROM pg_catalog.pg_namespace WHERE substr(nspname,1,%d)='%s'"},
|
{"SCHEMA", "SELECT nspname FROM pg_catalog.pg_namespace WHERE substr(nspname,1,%d)='%s'"},
|
||||||
{"SEQUENCE", "SELECT relname FROM pg_catalog.pg_class WHERE relkind='S' and substr(relname,1,%d)='%s'"},
|
{"SEQUENCE", "SELECT relname FROM pg_catalog.pg_class WHERE relkind='S' and substr(relname,1,%d)='%s'"},
|
||||||
{"TABLE", "SELECT relname FROM pg_catalog.pg_class WHERE (relkind='r' or relkind='v') and substr(relname,1,%d)='%s'"},
|
{"TABLE", Query_for_list_of_tables},
|
||||||
{"TEMP", NULL}, /* for CREATE TEMP TABLE ... */
|
{"TEMP", NULL}, /* for CREATE TEMP TABLE ... */
|
||||||
{"TRIGGER", "SELECT tgname FROM pg_catalog.pg_trigger WHERE substr(tgname,1,%d)='%s'"},
|
{"TRIGGER", "SELECT tgname FROM pg_catalog.pg_trigger WHERE substr(tgname,1,%d)='%s'"},
|
||||||
{"TYPE", "SELECT typname FROM pg_catalog.pg_type WHERE substr(typname,1,%d)='%s'"},
|
{"TYPE", "SELECT typname FROM pg_catalog.pg_type WHERE substr(typname,1,%d)='%s'"},
|
||||||
{"UNIQUE", NULL}, /* for CREATE UNIQUE INDEX ... */
|
{"UNIQUE", NULL}, /* for CREATE UNIQUE INDEX ... */
|
||||||
{"USER", "SELECT usename FROM pg_catalog.pg_user WHERE substr(usename,1,%d)='%s'"},
|
{"USER", Query_for_list_of_users},
|
||||||
{"VIEW", "SELECT viewname FROM pg_catalog.pg_views WHERE substr(viewname,1,%d)='%s'"},
|
{"VIEW", "SELECT viewname FROM pg_catalog.pg_views WHERE substr(viewname,1,%d)='%s'"},
|
||||||
{NULL, NULL} /* end of list */
|
{NULL, NULL} /* end of list */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* The query to get a list of tables and a list of indexes, which are used at
|
|
||||||
various places. */
|
|
||||||
#define Query_for_list_of_tables words_after_create[9].query
|
|
||||||
#define Query_for_list_of_indexes words_after_create[4].query
|
|
||||||
#define Query_for_list_of_databases words_after_create[1].query
|
|
||||||
#define Query_for_list_of_attributes "SELECT a.attname FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c WHERE c.oid = a.attrelid and a.attnum>0 and not a.attisdropped and substr(a.attname,1,%d)='%s' and c.relname='%s'"
|
|
||||||
#define Query_for_list_of_users words_after_create[14].query
|
|
||||||
|
|
||||||
/* A couple of macros to ease typing. You can use these to complete the given
|
/* A couple of macros to ease typing. You can use these to complete the given
|
||||||
string with
|
string with
|
||||||
1) The results from a query you pass it. (Perhaps one of those right above?)
|
1) The results from a query you pass it. (Perhaps one of those above?)
|
||||||
2) The items from a null-pointer-terminated list.
|
2) The items from a null-pointer-terminated list.
|
||||||
3) A string constant
|
3) A string constant
|
||||||
4) The list of attributes to the given table.
|
4) The list of attributes to the given table.
|
||||||
@ -375,7 +376,7 @@ psql_completion(char *text, int start, int end)
|
|||||||
* queries. */
|
* queries. */
|
||||||
|
|
||||||
if (snprintf(query_buffer, BUF_SIZE,
|
if (snprintf(query_buffer, BUF_SIZE,
|
||||||
"SELECT c1.relname FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid and c2.relname='%s'",
|
"SELECT c1.relname FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid and c2.relname='%s' and pg_catalog.pg_table_is_visible(c2.oid)",
|
||||||
prev2_wd) == -1)
|
prev2_wd) == -1)
|
||||||
ERROR_QUERY_TOO_LONG;
|
ERROR_QUERY_TOO_LONG;
|
||||||
else
|
else
|
||||||
@ -389,7 +390,8 @@ psql_completion(char *text, int start, int end)
|
|||||||
{
|
{
|
||||||
char *list_COMMENT[] =
|
char *list_COMMENT[] =
|
||||||
{"DATABASE", "INDEX", "RULE", "SCHEMA", "SEQUENCE", "TABLE", "TYPE", "VIEW",
|
{"DATABASE", "INDEX", "RULE", "SCHEMA", "SEQUENCE", "TABLE", "TYPE", "VIEW",
|
||||||
"COLUMN", "AGGREGATE", "FUNCTION", "OPERATOR", "TRIGGER", NULL};
|
"COLUMN", "AGGREGATE", "FUNCTION", "OPERATOR", "TRIGGER", "CONSTRAINT",
|
||||||
|
"DOMAIN", NULL};
|
||||||
|
|
||||||
COMPLETE_WITH_LIST(list_COMMENT);
|
COMPLETE_WITH_LIST(list_COMMENT);
|
||||||
}
|
}
|
||||||
@ -440,7 +442,7 @@ psql_completion(char *text, int start, int end)
|
|||||||
/* Complete USING with an index method */
|
/* Complete USING with an index method */
|
||||||
else if (strcasecmp(prev_wd, "USING") == 0)
|
else if (strcasecmp(prev_wd, "USING") == 0)
|
||||||
{
|
{
|
||||||
char *index_mth[] = {"BTREE", "RTREE", "HASH", NULL};
|
char *index_mth[] = {"BTREE", "RTREE", "HASH", "GIST", NULL};
|
||||||
|
|
||||||
COMPLETE_WITH_LIST(index_mth);
|
COMPLETE_WITH_LIST(index_mth);
|
||||||
}
|
}
|
||||||
@ -553,7 +555,7 @@ psql_completion(char *text, int start, int end)
|
|||||||
/* Complete GRANT/REVOKE with a list of privileges */
|
/* Complete GRANT/REVOKE with a list of privileges */
|
||||||
else if (strcasecmp(prev_wd, "GRANT") == 0 || strcasecmp(prev_wd, "REVOKE") == 0)
|
else if (strcasecmp(prev_wd, "GRANT") == 0 || strcasecmp(prev_wd, "REVOKE") == 0)
|
||||||
{
|
{
|
||||||
char *list_privileg[] = {"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "ALL", NULL};
|
char *list_privileg[] = {"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "REFERENCES", "TRIGGER", "CREATE", "TEMPORARY", "EXECUTE", "USAGE", "ALL", NULL};
|
||||||
|
|
||||||
COMPLETE_WITH_LIST(list_privileg);
|
COMPLETE_WITH_LIST(list_privileg);
|
||||||
}
|
}
|
||||||
@ -563,14 +565,15 @@ psql_completion(char *text, int start, int end)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Complete GRANT/REVOKE <sth> ON with a list of tables, views,
|
* Complete GRANT/REVOKE <sth> ON with a list of tables, views,
|
||||||
* schema, sequences, and indexes
|
* sequences, and indexes
|
||||||
|
*
|
||||||
|
* XXX should also offer DATABASE, FUNCTION, LANGUAGE, SCHEMA here
|
||||||
*/
|
*/
|
||||||
else if ((strcasecmp(prev3_wd, "GRANT") == 0 || strcasecmp(prev3_wd, "REVOKE") == 0) &&
|
else if ((strcasecmp(prev3_wd, "GRANT") == 0 || strcasecmp(prev3_wd, "REVOKE") == 0) &&
|
||||||
strcasecmp(prev_wd, "ON") == 0)
|
strcasecmp(prev_wd, "ON") == 0)
|
||||||
COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_class "
|
COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_class "
|
||||||
"WHERE relkind in ('r','i','S','v') AND "
|
"WHERE relkind in ('r','i','S','v') AND "
|
||||||
"substr(relname,1,%d)='%s' UNION "
|
"substr(relname,1,%d)='%s' AND pg_catalog.pg_table_is_visible(oid)");
|
||||||
"SELECT nspname FROM pg_catalog.pg_namespace;");
|
|
||||||
/* Complete "GRANT * ON * " with "TO" */
|
/* Complete "GRANT * ON * " with "TO" */
|
||||||
else if (strcasecmp(prev4_wd, "GRANT") == 0 && strcasecmp(prev2_wd, "ON") == 0)
|
else if (strcasecmp(prev4_wd, "GRANT") == 0 && strcasecmp(prev2_wd, "ON") == 0)
|
||||||
COMPLETE_WITH_CONST("TO");
|
COMPLETE_WITH_CONST("TO");
|
||||||
@ -745,7 +748,7 @@ psql_completion(char *text, int start, int end)
|
|||||||
|
|
||||||
/* UNLISTEN */
|
/* UNLISTEN */
|
||||||
else if (strcasecmp(prev_wd, "UNLISTEN") == 0)
|
else if (strcasecmp(prev_wd, "UNLISTEN") == 0)
|
||||||
COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_listener WHERE substr(relname,1,%d)='%s' UNION SELECT '*'::text");
|
COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_listener WHERE substr(relname,1,%d)='%s' UNION SELECT '*'::name");
|
||||||
|
|
||||||
/* UPDATE */
|
/* UPDATE */
|
||||||
/* If prev. word is UPDATE suggest a list of tables */
|
/* If prev. word is UPDATE suggest a list of tables */
|
||||||
@ -765,7 +768,7 @@ psql_completion(char *text, int start, int end)
|
|||||||
|
|
||||||
/* VACUUM */
|
/* VACUUM */
|
||||||
else if (strcasecmp(prev_wd, "VACUUM") == 0)
|
else if (strcasecmp(prev_wd, "VACUUM") == 0)
|
||||||
COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_class WHERE relkind='r' and substr(relname,1,%d)='%s' UNION SELECT 'FULL'::text UNION SELECT 'ANALYZE'::text");
|
COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_class WHERE relkind='r' and substr(relname,1,%d)='%s' and pg_catalog.pg_table_is_visible(oid) UNION SELECT 'FULL'::name UNION SELECT 'ANALYZE'::name");
|
||||||
else if (strcasecmp(prev2_wd, "VACUUM") == 0 && (strcasecmp(prev_wd, "FULL") == 0 || strcasecmp(prev_wd, "ANALYZE") == 0))
|
else if (strcasecmp(prev2_wd, "VACUUM") == 0 && (strcasecmp(prev_wd, "FULL") == 0 || strcasecmp(prev_wd, "ANALYZE") == 0))
|
||||||
COMPLETE_WITH_QUERY(Query_for_list_of_tables);
|
COMPLETE_WITH_QUERY(Query_for_list_of_tables);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user