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
0a8f6b79
Commit
0a8f6b79
authored
Jul 03, 2008
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix psql's \d and allied commands to work with all server versions back to 7.4.
Guillaume Lelarge, with some additional fixes by me.
parent
2c2aff6a
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
227 additions
and
132 deletions
+227
-132
doc/src/sgml/ref/psql-ref.sgml
doc/src/sgml/ref/psql-ref.sgml
+21
-25
src/bin/psql/describe.c
src/bin/psql/describe.c
+206
-107
No files found.
doc/src/sgml/ref/psql-ref.sgml
View file @
0a8f6b79
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.20
8 2008/06/11 10:48:16 heikki
Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.20
9 2008/07/03 03:37:16 tgl
Exp $
PostgreSQL documentation
-->
...
...
@@ -407,7 +407,7 @@ PostgreSQL documentation
<listitem>
<para>
Force <application>psql</application> to prompt for a
password before connecting to a database.
password before connecting to a database.
</para>
<para>
...
...
@@ -459,7 +459,7 @@ PostgreSQL documentation
<option>-f</> option, adding this option wraps
<command>BEGIN</>/<command>COMMIT</> around the script to execute it
as a single transaction. This ensures that either all the commands
complete successfully, or no changes are applied.
complete successfully, or no changes are applied.
</para>
<para>
...
...
@@ -542,8 +542,8 @@ PostgreSQL documentation
<para>
An alternative way to specify connection parameters is in a
<parameter>conninfo</parameter> string, which is used instead of a
database name. This mechanism give you very wide control over the
<parameter>conninfo</parameter> string, which is used instead of a
database name. This mechanism give you very wide control over the
connection. For example:
<programlisting>
$ <userinput>psql "service=myservice sslmode=require"</userinput>
...
...
@@ -873,7 +873,7 @@ testdb=>
Lists all available tablespaces. If <replaceable
class="parameter">pattern</replaceable>
is specified, only tablespaces whose names match the pattern are shown.
If <literal>+</literal> is appended to the command name, each object
If <literal>+</literal> is appended to the command name, each object
is listed with its associated permissions.
</para>
</listitem>
...
...
@@ -1511,7 +1511,7 @@ lo_import 152801
<listitem>
<para>
Sets the output format to one of <literal>unaligned</literal>,
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>aligned</literal>, <literal>wrapped</literal>,
<literal>html</literal>,
<literal>latex</literal>, or <literal>troff-ms</literal>.
Unique abbreviations are allowed. (That would mean one letter
...
...
@@ -2533,7 +2533,7 @@ testdb=> <userinput>\set content '''' `sed -e "s/'/''/g" -e 's/\\/\\\\/g' <
The full host name (with domain name) of the database server,
or <literal>[local]</literal> if the connection is over a Unix
domain socket, or
<literal>[local:<replaceable>/dir/name</replaceable>]</literal>,
<literal>[local:<replaceable>/dir/name</replaceable>]</literal>,
if the Unix domain socket is not at the compiled in default
location.
</para>
...
...
@@ -2857,28 +2857,24 @@ $endif
<itemizedlist>
<listitem>
<para>
In an earlier life <application>psql</application> allowed the
first argument of a single-letter backslash command to start
directly after the command, without intervening whitespace. For
compatibility this is still supported to some extent,
but we are not going to explain the details here as this use is
discouraged. If you get strange messages, keep this in mind.
For example:
<programlisting>
testdb=> <userinput>\foo</userinput>
Field separator is "oo".
</programlisting>
which is perhaps not what one would expect.
In an earlier life <application>psql</application> allowed the
first argument of a single-letter backslash command to start
directly after the command, without intervening whitespace.
As of <productname>PostgreSQL</productname> 8.4 this is no
longer allowed.
</para>
</listitem>
<listitem>
<para>
<application>psql</application> only works smoothly with servers
of the same version. That does not mean other combinations will
fail outright, but subtle and not-so-subtle problems might come
up. Backslash commands are particularly likely to fail if the
server is of a different version.
<application>psql</application> is only guaranteed to work smoothly
with servers of the same version. That does not mean other combinations
will fail outright, but subtle and not-so-subtle problems might come
up. Backslash commands are particularly likely to fail if the
server is of a newer version than <application>psql</> itself. However,
backslash commands of the <literal>\d</> family should work with
servers of versions back to 7.4, though not necessarily with servers
newer than <application>psql</> itself.
</para>
</listitem>
...
...
src/bin/psql/describe.c
View file @
0a8f6b79
/*
* psql - the PostgreSQL interactive terminal
*
* Support for the various \d ("describe") commands. Note that the current
* expectation is that all functions in this file will succeed when working
* with servers of versions 7.4 and up. It's okay to omit irrelevant
* information for an old server, but not to fail outright.
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.17
3 2008/05/13 00:23:17 alvherre
Exp $
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.17
4 2008/07/03 03:37:17 tgl
Exp $
*/
#include "postgres_fe.h"
...
...
@@ -38,7 +43,7 @@ static bool describeOneTSConfig(const char *oid, const char *nspname,
* Handlers for various slash commands displaying some sort of list
* of things in the database.
*
*
If you add something here, try to format the query
to look nice in -E output.
*
Note: try to format the queries
to look nice in -E output.
*----------------
*/
...
...
@@ -55,14 +60,16 @@ describeAggregates(const char *pattern, bool verbose)
initPQExpBuffer
(
&
buf
);
/*
* There are two kinds of aggregates: ones that work on particular types
* and ones that work on all (denoted by input type = "any")
*/
printfPQExpBuffer
(
&
buf
,
"SELECT n.nspname as
\"
%s
\"
,
\n
"
" p.proname AS
\"
%s
\"
,
\n
"
" pg_catalog.format_type(p.prorettype, NULL) AS
\"
%s
\"
,
\n
"
" pg_catalog.format_type(p.prorettype, NULL) AS
\"
%s
\"
,
\n
"
,
gettext_noop
(
"Schema"
),
gettext_noop
(
"Name"
),
gettext_noop
(
"Result data type"
));
if
(
pset
.
sversion
>=
80200
)
appendPQExpBuffer
(
&
buf
,
" CASE WHEN p.pronargs = 0
\n
"
" THEN CAST('*' AS pg_catalog.text)
\n
"
" ELSE
\n
"
...
...
@@ -72,22 +79,25 @@ describeAggregates(const char *pattern, bool verbose)
" FROM
\n
"
" pg_catalog.generate_series(0, pg_catalog.array_upper(p.proargtypes, 1)) AS s(i)
\n
"
" ), ', ')
\n
"
" END AS
\"
%s
\"
,
\n
"
" END AS
\"
%s
\"
,
\n
"
,
gettext_noop
(
"Argument data types"
));
else
appendPQExpBuffer
(
&
buf
,
" pg_catalog.format_type(p.proargtypes[0], NULL) AS
\"
%s
\"
,
\n
"
,
gettext_noop
(
"Argument data types"
));
appendPQExpBuffer
(
&
buf
,
" pg_catalog.obj_description(p.oid, 'pg_proc') as
\"
%s
\"\n
"
"FROM pg_catalog.pg_proc p
\n
"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
\n
"
"WHERE p.proisagg
\n
"
,
gettext_noop
(
"Schema"
),
gettext_noop
(
"Name"
),
gettext_noop
(
"Result data type"
),
gettext_noop
(
"Argument data types"
),
gettext_noop
(
"Description"
));
processSQLNamePattern
(
pset
.
db
,
&
buf
,
pattern
,
true
,
false
,
"n.nspname"
,
"p.proname"
,
NULL
,
"pg_catalog.pg_function_is_visible(p.oid)"
);
appendPQExpBuffer
(
&
buf
,
"ORDER BY 1, 2,
3
;"
);
appendPQExpBuffer
(
&
buf
,
"ORDER BY 1, 2,
4
;"
);
res
=
PSQLexec
(
buf
.
data
,
false
);
termPQExpBuffer
(
&
buf
);
...
...
@@ -116,8 +126,8 @@ describeTablespaces(const char *pattern, bool verbose)
if
(
pset
.
sversion
<
80000
)
{
fprintf
(
stderr
,
_
(
"The server
version (
%d) does not support tablespaces.
\n
"
),
pset
.
sversion
);
fprintf
(
stderr
,
_
(
"The server
(version %d.
%d) does not support tablespaces.
\n
"
),
pset
.
sversion
/
10000
,
(
pset
.
sversion
/
100
)
%
100
);
return
true
;
}
...
...
@@ -133,9 +143,11 @@ describeTablespaces(const char *pattern, bool verbose)
if
(
verbose
)
appendPQExpBuffer
(
&
buf
,
",
\n
spcacl AS
\"
%s
\"
"
",
\n
pg_catalog.shobj_description(oid, 'pg_tablespace') AS
\"
%s
\"
"
,
gettext_noop
(
"Access privileges"
),
",
\n
spcacl AS
\"
%s
\"
"
,
gettext_noop
(
"Access privileges"
));
if
(
verbose
&&
pset
.
sversion
>=
80200
)
appendPQExpBuffer
(
&
buf
,
",
\n
pg_catalog.shobj_description(oid, 'pg_tablespace') AS
\"
%s
\"
"
,
gettext_noop
(
"Description"
));
appendPQExpBuffer
(
&
buf
,
...
...
@@ -179,7 +191,13 @@ describeFunctions(const char *pattern, bool verbose)
"SELECT n.nspname as
\"
%s
\"
,
\n
"
" p.proname as
\"
%s
\"
,
\n
"
" CASE WHEN p.proretset THEN 'setof ' ELSE '' END ||
\n
"
" pg_catalog.format_type(p.prorettype, NULL) as
\"
%s
\"
,
\n
"
" pg_catalog.format_type(p.prorettype, NULL) as
\"
%s
\"
,
\n
"
,
gettext_noop
(
"Schema"
),
gettext_noop
(
"Name"
),
gettext_noop
(
"Result data type"
));
if
(
pset
.
sversion
>=
80100
)
appendPQExpBuffer
(
&
buf
,
" CASE WHEN proallargtypes IS NOT NULL THEN
\n
"
" pg_catalog.array_to_string(ARRAY(
\n
"
" SELECT
\n
"
...
...
@@ -208,10 +226,11 @@ describeFunctions(const char *pattern, bool verbose)
" pg_catalog.generate_series(0, pg_catalog.array_upper(p.proargtypes, 1)) AS s(i)
\n
"
" ), ', ')
\n
"
" END AS
\"
%s
\"
"
,
gettext_noop
(
"Schema"
),
gettext_noop
(
"Name"
),
gettext_noop
(
"Result data type"
),
gettext_noop
(
"Argument data types"
));
else
appendPQExpBuffer
(
&
buf
,
" pg_catalog.oidvectortypes(p.proargtypes) as
\"
%s
\"
"
,
gettext_noop
(
"Argument data types"
));
if
(
verbose
)
appendPQExpBuffer
(
&
buf
,
...
...
@@ -220,7 +239,7 @@ describeFunctions(const char *pattern, bool verbose)
" WHEN p.provolatile = 's' THEN 'stable'
\n
"
" WHEN p.provolatile = 'v' THEN 'volatile'
\n
"
"END as
\"
%s
\"
"
",
\n
r.rolname
as
\"
%s
\"
,
\n
"
",
\n
pg_catalog.pg_get_userbyid(p.proowner)
as
\"
%s
\"
,
\n
"
" l.lanname as
\"
%s
\"
,
\n
"
" p.prosrc as
\"
%s
\"
,
\n
"
" pg_catalog.obj_description(p.oid, 'pg_proc') as
\"
%s
\"
"
,
...
...
@@ -230,31 +249,27 @@ describeFunctions(const char *pattern, bool verbose)
gettext_noop
(
"Source code"
),
gettext_noop
(
"Description"
));
if
(
!
verbose
)
appendPQExpBuffer
(
&
buf
,
"
\n
FROM pg_catalog.pg_proc p"
"
\n
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
\n
"
);
else
appendPQExpBuffer
(
&
buf
,
"
\n
FROM pg_catalog.pg_proc p"
"
\n
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
\n
"
);
if
(
verbose
)
appendPQExpBuffer
(
&
buf
,
"
\n
FROM pg_catalog.pg_proc p"
"
\n
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace"
"
\n
LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang"
"
\n
JOIN pg_catalog.pg_roles r ON r.oid = p.proowner
\n
"
);
" LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang
\n
"
);
/*
* we skip in/out funcs by excluding functions that take or return cstring
*/
appendPQExpBuffer
(
&
buf
,
"WHERE p.prorettype <> 'pg_catalog.cstring'::pg_catalog.regtype
\n
"
" AND (p.proargtypes[0] IS NULL
\n
"
" OR p.proargtypes[0] <> 'pg_catalog.cstring'::pg_catalog.regtype)
\n
"
" AND p.proargtypes[0] IS DISTINCT FROM 'pg_catalog.cstring'::pg_catalog.regtype
\n
"
" AND NOT p.proisagg
\n
"
);
processSQLNamePattern
(
pset
.
db
,
&
buf
,
pattern
,
true
,
false
,
"n.nspname"
,
"p.proname"
,
NULL
,
"pg_catalog.pg_function_is_visible(p.oid)"
);
appendPQExpBuffer
(
&
buf
,
"ORDER BY 1, 2,
3,
4;"
);
appendPQExpBuffer
(
&
buf
,
"ORDER BY 1, 2, 4;"
);
res
=
PSQLexec
(
buf
.
data
,
false
);
termPQExpBuffer
(
&
buf
);
...
...
@@ -299,9 +314,13 @@ describeTypes(const char *pattern, bool verbose)
" WHEN t.typlen < 0
\n
"
" THEN CAST('var' AS pg_catalog.text)
\n
"
" ELSE CAST(t.typlen AS pg_catalog.text)
\n
"
" END AS
\"
%s
\"
,
\n
"
" END AS
\"
%s
\"
,
\n
"
,
gettext_noop
(
"Internal name"
),
gettext_noop
(
"Size"
));
if
(
verbose
&&
pset
.
sversion
>=
80300
)
appendPQExpBuffer
(
&
buf
,
" pg_catalog.array_to_string(
\n
"
"
ARRAY(
\n
"
"
ARRAY(
\n
"
" SELECT e.enumlabel
\n
"
" FROM pg_catalog.pg_enum e
\n
"
" WHERE e.enumtypid = t.oid
\n
"
...
...
@@ -309,10 +328,8 @@ describeTypes(const char *pattern, bool verbose)
" ),
\n
"
" E'
\\
n'
\n
"
" ) AS
\"
%s
\"
,
\n
"
,
gettext_noop
(
"Internal name"
),
gettext_noop
(
"Size"
),
gettext_noop
(
"Elements"
));
appendPQExpBuffer
(
&
buf
,
" pg_catalog.obj_description(t.oid, 'pg_type') as
\"
%s
\"\n
"
,
gettext_noop
(
"Description"
));
...
...
@@ -321,13 +338,20 @@ describeTypes(const char *pattern, bool verbose)
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
\n
"
);
/*
* do not include
array types (start with underscore); do not includ
e
* comp
lex types (typrelid!=0) unless they are standalone comp
osite types
* do not include
complex types (typrelid!=0) unless they are standalon
e
* composite types
*/
appendPQExpBuffer
(
&
buf
,
"WHERE (t.typrelid = 0 "
);
appendPQExpBuffer
(
&
buf
,
"OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c "
"WHERE c.oid = t.typrelid)) "
);
appendPQExpBuffer
(
&
buf
,
"AND t.typname !~ '^_'
\n
"
);
"WHERE c.oid = t.typrelid))
\n
"
);
/*
* do not include array types (before 8.3 we have to use the assumption
* that their names start with underscore)
*/
if
(
pset
.
sversion
>=
80300
)
appendPQExpBuffer
(
&
buf
,
" AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)
\n
"
);
else
appendPQExpBuffer
(
&
buf
,
" AND t.typname !~ '^_'
\n
"
);
/* Match name pattern against either internal or external name */
processSQLNamePattern
(
pset
.
db
,
&
buf
,
pattern
,
true
,
false
,
...
...
@@ -419,32 +443,31 @@ listAllDbs(bool verbose)
printfPQExpBuffer
(
&
buf
,
"SELECT d.datname as
\"
%s
\"
,
\n
"
"
r.rolname
as
\"
%s
\"
,
\n
"
"
pg_catalog.pg_get_userbyid(d.datdba)
as
\"
%s
\"
,
\n
"
" pg_catalog.pg_encoding_to_char(d.encoding) as
\"
%s
\"
,
\n
"
" d.datacl as
\"
%s
\"
"
,
gettext_noop
(
"Name"
),
gettext_noop
(
"Owner"
),
gettext_noop
(
"Encoding"
),
gettext_noop
(
"Access Privileges"
));
if
(
verbose
)
{
if
(
verbose
&&
pset
.
sversion
>=
80200
)
appendPQExpBuffer
(
&
buf
,
",
\n
CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')
\n
"
" THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))
\n
"
" ELSE 'No Access'
\n
"
" END as
\"
%s
\"
"
,
gettext_noop
(
"Size"
));
if
(
verbose
&&
pset
.
sversion
>=
80000
)
appendPQExpBuffer
(
&
buf
,
",
\n
t.spcname as
\"
%s
\"
"
,
gettext_noop
(
"Tablespace"
));
appendPQExpBuffer
(
&
buf
,
if
(
verbose
&&
pset
.
sversion
>=
80200
)
appendPQExpBuffer
(
&
buf
,
",
\n
pg_catalog.shobj_description(d.oid, 'pg_database') as
\"
%s
\"
"
,
gettext_noop
(
"Description"
));
}
appendPQExpBuffer
(
&
buf
,
"
\n
FROM pg_catalog.pg_database d"
"
\n
JOIN pg_catalog.pg_roles r ON d.datdba = r.oid
\n
"
);
if
(
verbose
)
"
\n
FROM pg_catalog.pg_database d
\n
"
);
if
(
verbose
&&
pset
.
sversion
>=
80000
)
appendPQExpBuffer
(
&
buf
,
" JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid
\n
"
);
appendPQExpBuffer
(
&
buf
,
"ORDER BY 1;"
);
...
...
@@ -484,17 +507,23 @@ permissionsList(const char *pattern)
printfPQExpBuffer
(
&
buf
,
"SELECT n.nspname as
\"
%s
\"
,
\n
"
" c.relname as
\"
%s
\"
,
\n
"
" CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'S' THEN '%s' END as
\"
%s
\"
,
\n
"
" pg_catalog.array_to_string(c.relacl, E'
\\
n') as
\"
%s
\"\n
"
"FROM pg_catalog.pg_class c
\n
"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
\n
"
"WHERE c.relkind IN ('r', 'v', 'S')
\n
"
,
" CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'S' THEN '%s' END as
\"
%s
\"
,
\n
"
,
gettext_noop
(
"Schema"
),
gettext_noop
(
"Name"
),
gettext_noop
(
"table"
),
gettext_noop
(
"view"
),
gettext_noop
(
"sequence"
),
gettext_noop
(
"Type"
),
gettext_noop
(
"Type"
));
if
(
pset
.
sversion
>=
80100
)
appendPQExpBuffer
(
&
buf
,
" pg_catalog.array_to_string(c.relacl, E'
\\
n') as
\"
%s
\"\n
"
,
gettext_noop
(
"Access privileges"
));
else
appendPQExpBuffer
(
&
buf
,
" pg_catalog.array_to_string(c.relacl, '
\\
n') as
\"
%s
\"\n
"
,
gettext_noop
(
"Access privileges"
));
appendPQExpBuffer
(
&
buf
,
"FROM pg_catalog.pg_class c
\n
"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
\n
"
"WHERE c.relkind IN ('r', 'v', 'S')
\n
"
);
/*
* Unless a schema pattern is specified, we suppress system and temp
* tables, since they normally aren't very interesting from a permissions
...
...
@@ -694,7 +723,6 @@ objectDescription(const char *pattern)
}
/*
* describeTableDetails (for \d)
*
...
...
@@ -815,10 +843,10 @@ describeOneTableDetails(const char *schemaname,
/* Get general table info */
printfPQExpBuffer
(
&
buf
,
"SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules,
\n
"
"relhasoids
%s
\n
"
"SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules, "
"relhasoids
%s
\n
"
"FROM pg_catalog.pg_class WHERE oid = '%s'"
,
pset
.
sversion
>=
80000
?
", reltablespace"
:
""
,
(
pset
.
sversion
>=
80000
?
", reltablespace"
:
""
)
,
oid
);
res
=
PSQLexec
(
buf
.
data
,
false
);
if
(
!
res
)
...
...
@@ -833,7 +861,6 @@ describeOneTableDetails(const char *schemaname,
goto
error_return
;
}
/* FIXME: check for null pointers here? */
tableinfo
.
checks
=
atoi
(
PQgetvalue
(
res
,
0
,
2
));
tableinfo
.
triggers
=
atoi
(
PQgetvalue
(
res
,
0
,
3
));
tableinfo
.
relkind
=
*
(
PQgetvalue
(
res
,
0
,
1
));
...
...
@@ -930,7 +957,9 @@ describeOneTableDetails(const char *schemaname,
{
PGresult
*
result
;
printfPQExpBuffer
(
&
buf
,
"SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true)"
,
oid
);
printfPQExpBuffer
(
&
buf
,
"SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true)"
,
oid
);
result
=
PSQLexec
(
buf
.
data
,
false
);
if
(
!
result
)
goto
error_return
;
...
...
@@ -984,7 +1013,12 @@ describeOneTableDetails(const char *schemaname,
PGresult
*
result
;
printfPQExpBuffer
(
&
buf
,
"SELECT i.indisunique, i.indisprimary, i.indisclustered, i.indisvalid, a.amname, c2.relname,
\n
"
"SELECT i.indisunique, i.indisprimary, i.indisclustered, "
);
if
(
pset
.
sversion
>=
80200
)
appendPQExpBuffer
(
&
buf
,
"i.indisvalid, "
);
else
appendPQExpBuffer
(
&
buf
,
"true as indisvalid, "
);
appendPQExpBuffer
(
&
buf
,
"a.amname, c2.relname,
\n
"
" pg_catalog.pg_get_expr(i.indpred, i.indrelid, true)
\n
"
"FROM pg_catalog.pg_index i, pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_am a
\n
"
"WHERE i.indexrelid = c.oid AND c.oid = '%s' AND c.relam = a.oid
\n
"
...
...
@@ -1033,7 +1067,6 @@ describeOneTableDetails(const char *schemaname,
printTableAddFooter
(
&
cont
,
tmpbuf
.
data
);
add_tablespace_footer
(
&
cont
,
tableinfo
.
relkind
,
tableinfo
.
tablespace
,
true
);
}
PQclear
(
result
);
...
...
@@ -1086,9 +1119,16 @@ describeOneTableDetails(const char *schemaname,
if
(
tableinfo
.
hasindex
)
{
printfPQExpBuffer
(
&
buf
,
"SELECT c2.relname, i.indisprimary, i.indisunique, i.indisclustered, i.indisvalid, "
"pg_catalog.pg_get_indexdef(i.indexrelid, 0, true), c2.reltablespace
\n
"
"FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i
\n
"
"SELECT c2.relname, i.indisprimary, i.indisunique, i.indisclustered, "
);
if
(
pset
.
sversion
>=
80200
)
appendPQExpBuffer
(
&
buf
,
"i.indisvalid, "
);
else
appendPQExpBuffer
(
&
buf
,
"true as indisvalid, "
);
appendPQExpBuffer
(
&
buf
,
"pg_catalog.pg_get_indexdef(i.indexrelid, 0, true)"
);
if
(
pset
.
sversion
>=
80000
)
appendPQExpBuffer
(
&
buf
,
", c2.reltablespace"
);
appendPQExpBuffer
(
&
buf
,
"
\n
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i
\n
"
"WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid
\n
"
"ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname"
,
oid
);
...
...
@@ -1134,9 +1174,10 @@ describeOneTableDetails(const char *schemaname,
printTableAddFooter
(
&
cont
,
buf
.
data
);
/* Print tablespace of the index on the same line */
add_tablespace_footer
(
&
cont
,
'i'
,
atooid
(
PQgetvalue
(
result
,
i
,
6
)),
false
);
if
(
pset
.
sversion
>=
80000
)
add_tablespace_footer
(
&
cont
,
'i'
,
atooid
(
PQgetvalue
(
result
,
i
,
6
)),
false
);
}
}
PQclear
(
result
);
...
...
@@ -1149,7 +1190,7 @@ describeOneTableDetails(const char *schemaname,
"SELECT r.conname, "
"pg_catalog.pg_get_constraintdef(r.oid, true)
\n
"
"FROM pg_catalog.pg_constraint r
\n
"
"WHERE r.conrelid = '%s' AND r.contype = 'c'
ORDER BY 1"
,
"WHERE r.conrelid = '%s' AND r.contype = 'c'
\n
ORDER BY 1"
,
oid
);
result
=
PSQLexec
(
buf
.
data
,
false
);
if
(
!
result
)
...
...
@@ -1178,7 +1219,7 @@ describeOneTableDetails(const char *schemaname,
{
printfPQExpBuffer
(
&
buf
,
"SELECT conname,
\n
"
" pg_catalog.pg_get_constraintdef(oid, true) as condef
\n
"
" pg_catalog.pg_get_constraintdef(
r.
oid, true) as condef
\n
"
"FROM pg_catalog.pg_constraint r
\n
"
"WHERE r.conrelid = '%s' AND r.contype = 'f' ORDER BY 1"
,
oid
);
...
...
@@ -1209,7 +1250,7 @@ describeOneTableDetails(const char *schemaname,
{
printfPQExpBuffer
(
&
buf
,
"SELECT conname, conrelid::pg_catalog.regclass,
\n
"
" pg_catalog.pg_get_constraintdef(oid, true) as condef
\n
"
" pg_catalog.pg_get_constraintdef(
c.
oid, true) as condef
\n
"
"FROM pg_catalog.pg_constraint c
\n
"
"WHERE c.confrelid = '%s' AND c.contype = 'f' ORDER BY 1"
,
oid
);
...
...
@@ -1240,11 +1281,11 @@ describeOneTableDetails(const char *schemaname,
/* print rules */
if
(
tableinfo
.
hasrules
)
{
if
(
pset
.
sversion
<
80300
)
if
(
pset
.
sversion
>=
80300
)
{
printfPQExpBuffer
(
&
buf
,
"SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
"
'O'::char AS
ev_enabled
\n
"
"ev_enabled
\n
"
"FROM pg_catalog.pg_rewrite r
\n
"
"WHERE r.ev_class = '%s' ORDER BY 1"
,
oid
);
...
...
@@ -1253,7 +1294,7 @@ describeOneTableDetails(const char *schemaname,
{
printfPQExpBuffer
(
&
buf
,
"SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
"ev_enabled
\n
"
"
'O'::char AS
ev_enabled
\n
"
"FROM pg_catalog.pg_rewrite r
\n
"
"WHERE r.ev_class = '%s' ORDER BY 1"
,
oid
);
...
...
@@ -1336,13 +1377,23 @@ describeOneTableDetails(const char *schemaname,
if
(
tableinfo
.
triggers
)
{
printfPQExpBuffer
(
&
buf
,
"SELECT t.tgname, pg_catalog.pg_get_triggerdef(t.oid), "
"SELECT t.tgname, "
"pg_catalog.pg_get_triggerdef(t.oid), "
"t.tgenabled
\n
"
"FROM pg_catalog.pg_trigger t
\n
"
"WHERE t.tgrelid = '%s' "
"AND t.tgconstraint = 0
\n
"
"ORDER BY 1"
,
"WHERE t.tgrelid = '%s' AND "
,
oid
);
if
(
pset
.
sversion
>=
80300
)
appendPQExpBuffer
(
&
buf
,
"t.tgconstraint = 0"
);
else
appendPQExpBuffer
(
&
buf
,
"(NOT tgisconstraint "
" OR NOT EXISTS"
" (SELECT 1 FROM pg_catalog.pg_depend d "
" JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) "
" WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))"
);
appendPQExpBuffer
(
&
buf
,
"
\n
ORDER BY 1"
);
result
=
PSQLexec
(
buf
.
data
,
false
);
if
(
!
result
)
goto
error_return
;
...
...
@@ -1511,7 +1562,8 @@ add_tablespace_footer(printTableContent *const cont, char relkind,
{
/*
* We ignore the database default tablespace so that users not using
* tablespaces don't need to know about them.
* tablespaces don't need to know about them. This case also covers
* pre-8.0 servers, for which tablespace will always be 0.
*/
if
(
tablespace
!=
0
)
{
...
...
@@ -1519,8 +1571,9 @@ add_tablespace_footer(printTableContent *const cont, char relkind,
PQExpBufferData
buf
;
initPQExpBuffer
(
&
buf
);
printfPQExpBuffer
(
&
buf
,
"SELECT spcname FROM pg_tablespace
\n
"
"WHERE oid = '%u';"
,
tablespace
);
printfPQExpBuffer
(
&
buf
,
"SELECT spcname FROM pg_catalog.pg_tablespace
\n
"
"WHERE oid = '%u'"
,
tablespace
);
result
=
PSQLexec
(
buf
.
data
,
false
);
if
(
!
result
)
return
;
...
...
@@ -1572,7 +1625,9 @@ describeRoles(const char *pattern, bool verbose)
initPQExpBuffer
(
&
buf
);
appendPQExpBufferStr
(
&
buf
,
if
(
pset
.
sversion
>=
80100
)
{
printfPQExpBuffer
(
&
buf
,
"SELECT r.rolname, r.rolsuper, r.rolinherit,
\n
"
" r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,
\n
"
" r.rolconnlimit,
\n
"
...
...
@@ -1581,16 +1636,31 @@ describeRoles(const char *pattern, bool verbose)
" JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)
\n
"
" WHERE m.member = r.oid) as memberof"
);
if
(
verbose
)
{
appendPQExpBufferStr
(
&
buf
,
"
\n
, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description"
);
ncols
++
;
}
appendPQExpBuffer
(
&
buf
,
"
\n
FROM pg_catalog.pg_roles r
\n
"
);
if
(
verbose
&&
pset
.
sversion
>=
80200
)
{
appendPQExpBufferStr
(
&
buf
,
"
\n
, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description"
);
ncols
++
;
}
processSQLNamePattern
(
pset
.
db
,
&
buf
,
pattern
,
false
,
false
,
NULL
,
"r.rolname"
,
NULL
,
NULL
);
appendPQExpBufferStr
(
&
buf
,
"
\n
FROM pg_catalog.pg_roles r
\n
"
);
processSQLNamePattern
(
pset
.
db
,
&
buf
,
pattern
,
false
,
false
,
NULL
,
"r.rolname"
,
NULL
,
NULL
);
}
else
{
printfPQExpBuffer
(
&
buf
,
"SELECT u.usename AS rolname,
\n
"
" u.usesuper AS rolsuper,
\n
"
" true AS rolinherit, false AS rolcreaterole,
\n
"
" u.usecreatedb AS rolcreatedb, true AS rolcanlogin,
\n
"
" -1 AS rolconnlimit,
\n
"
" ARRAY(SELECT g.groname FROM pg_catalog.pg_group g WHERE u.usesysid = ANY(g.grolist)) as memberof"
"
\n
FROM pg_catalog.pg_user u
\n
"
);
processSQLNamePattern
(
pset
.
db
,
&
buf
,
pattern
,
false
,
false
,
NULL
,
"u.usename"
,
NULL
,
NULL
);
}
appendPQExpBuffer
(
&
buf
,
"ORDER BY 1;"
);
...
...
@@ -1607,7 +1677,7 @@ describeRoles(const char *pattern, bool verbose)
printTableAddHeader
(
&
cont
,
gettext_noop
(
"Attributes"
),
true
,
align
);
printTableAddHeader
(
&
cont
,
gettext_noop
(
"Member of"
),
true
,
align
);
if
(
verbose
)
if
(
verbose
&&
pset
.
sversion
>=
80200
)
printTableAddHeader
(
&
cont
,
gettext_noop
(
"Description"
),
true
,
align
);
for
(
i
=
0
;
i
<
nrows
;
i
++
)
...
...
@@ -1650,7 +1720,7 @@ describeRoles(const char *pattern, bool verbose)
printTableAddCell
(
&
cont
,
PQgetvalue
(
res
,
i
,
7
),
false
);
if
(
verbose
)
if
(
verbose
&&
pset
.
sversion
>=
80200
)
printTableAddCell
(
&
cont
,
PQgetvalue
(
res
,
i
,
8
),
false
);
}
termPQExpBuffer
(
&
buf
);
...
...
@@ -1716,10 +1786,14 @@ listTables(const char *tabtypes, const char *pattern, bool verbose)
"SELECT n.nspname as
\"
%s
\"
,
\n
"
" c.relname as
\"
%s
\"
,
\n
"
" CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'i' THEN '%s' WHEN 'S' THEN '%s' WHEN 's' THEN '%s' END as
\"
%s
\"
,
\n
"
"
r.rolname
as
\"
%s
\"
"
,
"
pg_catalog.pg_get_userbyid(c.relowner)
as
\"
%s
\"
"
,
gettext_noop
(
"Schema"
),
gettext_noop
(
"Name"
),
gettext_noop
(
"table"
),
gettext_noop
(
"view"
),
gettext_noop
(
"index"
),
gettext_noop
(
"sequence"
),
gettext_noop
(
"special"
),
gettext_noop
(
"table"
),
gettext_noop
(
"view"
),
gettext_noop
(
"index"
),
gettext_noop
(
"sequence"
),
gettext_noop
(
"special"
),
gettext_noop
(
"Type"
),
gettext_noop
(
"Owner"
));
...
...
@@ -1728,19 +1802,17 @@ listTables(const char *tabtypes, const char *pattern, bool verbose)
",
\n
c2.relname as
\"
%s
\"
"
,
gettext_noop
(
"Table"
));
if
(
verbose
)
{
if
(
verbose
&&
pset
.
sversion
>=
80100
)
appendPQExpBuffer
(
&
buf
,
",
\n
pg_catalog.pg_size_pretty(pg_catalog.pg_relation_size(c.oid)) as
\"
%s
\"
"
,
gettext_noop
(
"Size"
));
gettext_noop
(
"Size"
));
if
(
verbose
)
appendPQExpBuffer
(
&
buf
,
",
\n
pg_catalog.obj_description(c.oid, 'pg_class') as
\"
%s
\"
"
,
gettext_noop
(
"Description"
));
}
appendPQExpBuffer
(
&
buf
,
"
\n
FROM pg_catalog.pg_class c"
"
\n
JOIN pg_catalog.pg_roles r ON r.oid = c.relowner"
"
\n
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
);
if
(
showIndexes
)
appendPQExpBuffer
(
&
buf
,
...
...
@@ -1985,7 +2057,7 @@ listSchemas(const char *pattern, bool verbose)
initPQExpBuffer
(
&
buf
);
printfPQExpBuffer
(
&
buf
,
"SELECT n.nspname AS
\"
%s
\"
,
\n
"
"
r.rolname
AS
\"
%s
\"
"
,
"
pg_catalog.pg_get_userbyid(n.nspowner)
AS
\"
%s
\"
"
,
gettext_noop
(
"Name"
),
gettext_noop
(
"Owner"
));
...
...
@@ -1997,8 +2069,7 @@ listSchemas(const char *pattern, bool verbose)
gettext_noop
(
"Description"
));
appendPQExpBuffer
(
&
buf
,
"
\n
FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_roles r
\n
"
" ON n.nspowner=r.oid
\n
"
"
\n
FROM pg_catalog.pg_namespace n
\n
"
"WHERE (n.nspname !~ '^pg_temp_' OR
\n
"
" n.nspname = (pg_catalog.current_schemas(true))[1])
\n
"
);
/* temp schema is first */
...
...
@@ -2035,6 +2106,13 @@ listTSParsers(const char *pattern, bool verbose)
PGresult
*
res
;
printQueryOpt
myopt
=
pset
.
popt
;
if
(
pset
.
sversion
<
80300
)
{
fprintf
(
stderr
,
_
(
"The server (version %d.%d) does not support full text search.
\n
"
),
pset
.
sversion
/
10000
,
(
pset
.
sversion
/
100
)
%
100
);
return
true
;
}
if
(
verbose
)
return
listTSParsersVerbose
(
pattern
);
...
...
@@ -2261,6 +2339,13 @@ listTSDictionaries(const char *pattern, bool verbose)
PGresult
*
res
;
printQueryOpt
myopt
=
pset
.
popt
;
if
(
pset
.
sversion
<
80300
)
{
fprintf
(
stderr
,
_
(
"The server (version %d.%d) does not support full text search.
\n
"
),
pset
.
sversion
/
10000
,
(
pset
.
sversion
/
100
)
%
100
);
return
true
;
}
initPQExpBuffer
(
&
buf
);
printfPQExpBuffer
(
&
buf
,
...
...
@@ -2322,6 +2407,13 @@ listTSTemplates(const char *pattern, bool verbose)
PGresult
*
res
;
printQueryOpt
myopt
=
pset
.
popt
;
if
(
pset
.
sversion
<
80300
)
{
fprintf
(
stderr
,
_
(
"The server (version %d.%d) does not support full text search.
\n
"
),
pset
.
sversion
/
10000
,
(
pset
.
sversion
/
100
)
%
100
);
return
true
;
}
initPQExpBuffer
(
&
buf
);
if
(
verbose
)
...
...
@@ -2383,6 +2475,13 @@ listTSConfigs(const char *pattern, bool verbose)
PGresult
*
res
;
printQueryOpt
myopt
=
pset
.
popt
;
if
(
pset
.
sversion
<
80300
)
{
fprintf
(
stderr
,
_
(
"The server (version %d.%d) does not support full text search.
\n
"
),
pset
.
sversion
/
10000
,
(
pset
.
sversion
/
100
)
%
100
);
return
true
;
}
if
(
verbose
)
return
listTSConfigsVerbose
(
pattern
);
...
...
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