2000-01-18 23:30:24 +00:00
|
|
|
/*
|
|
|
|
* psql - the PostgreSQL interactive terminal
|
|
|
|
*
|
2000-01-29 16:58:54 +00:00
|
|
|
* Copyright 2000 by PostgreSQL Global Development Group
|
2000-01-18 23:30:24 +00:00
|
|
|
*
|
2001-08-10 18:57:42 +00:00
|
|
|
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.38 2001/08/10 18:57:39 tgl Exp $
|
2000-01-18 23:30:24 +00:00
|
|
|
*/
|
2001-02-10 02:31:31 +00:00
|
|
|
#include "postgres_fe.h"
|
1999-11-04 21:56:02 +00:00
|
|
|
#include "describe.h"
|
|
|
|
|
2000-02-16 13:15:26 +00:00
|
|
|
#include "libpq-fe.h"
|
1999-11-04 21:56:02 +00:00
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
#include "settings.h"
|
|
|
|
#include "print.h"
|
|
|
|
#include "variables.h"
|
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
#define _(x) gettext((x))
|
|
|
|
|
1999-11-04 21:56:02 +00:00
|
|
|
|
|
|
|
/*----------------
|
|
|
|
* Handlers for various slash commands displaying some sort of list
|
|
|
|
* of things in the database.
|
|
|
|
*
|
2000-01-12 19:36:36 +00:00
|
|
|
* If you add something here, try to format the query to look nice in -E output.
|
1999-11-04 21:56:02 +00:00
|
|
|
*----------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* the maximal size of regular expression we'll accept here */
|
2001-08-05 22:13:46 +00:00
|
|
|
/* (it is safe to just change this here) */
|
|
|
|
#define REGEXP_CUTOFF (10 * NAMEDATALEN)
|
1999-11-04 21:56:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* \da
|
|
|
|
* takes an optional regexp to match specific aggregates by name
|
|
|
|
*/
|
|
|
|
bool
|
2000-01-14 22:18:03 +00:00
|
|
|
describeAggregates(const char *name)
|
1999-11-04 21:56:02 +00:00
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
char buf[384 + REGEXP_CUTOFF];
|
1999-11-04 23:14:30 +00:00
|
|
|
PGresult *res;
|
2000-01-14 22:18:03 +00:00
|
|
|
printQueryOpt myopt = pset.popt;
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* There are two kinds of aggregates: ones that work on particular
|
|
|
|
* types ones that work on all
|
|
|
|
*/
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf, sizeof(buf),
|
|
|
|
"SELECT a.aggname AS \"%s\",\n"
|
|
|
|
" CASE a.aggbasetype\n"
|
|
|
|
" WHEN 0 THEN CAST('%s' AS text)\n"
|
|
|
|
" ELSE format_type(a.aggbasetype, NULL)\n"
|
|
|
|
" END AS \"%s\",\n"
|
2001-08-10 18:57:42 +00:00
|
|
|
" obj_description(a.oid, 'pg_aggregate') as \"%s\"\n"
|
2001-06-30 17:26:12 +00:00
|
|
|
"FROM pg_aggregate a\n",
|
|
|
|
_("Name"), _("(all types)"),
|
|
|
|
_("Data type"), _("Description") );
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
if (name)
|
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "WHERE a.aggname ~ '^");
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
strncat(buf, name, REGEXP_CUTOFF);
|
|
|
|
strcat(buf, "'\n");
|
1999-11-04 23:14:30 +00:00
|
|
|
}
|
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "ORDER BY 1, 2;");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
res = PSQLexec(buf);
|
1999-11-04 23:14:30 +00:00
|
|
|
if (!res)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
myopt.nullPrint = NULL;
|
2001-06-30 17:26:12 +00:00
|
|
|
myopt.title = _("List of aggregate functions");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
printQuery(res, &myopt, pset.queryFout);
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
PQclear(res);
|
|
|
|
return true;
|
1999-11-04 21:56:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* \df
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
* Takes an optional regexp to narrow down the function name
|
1999-11-04 21:56:02 +00:00
|
|
|
*/
|
|
|
|
bool
|
2000-01-14 22:18:03 +00:00
|
|
|
describeFunctions(const char *name, bool verbose)
|
1999-11-04 21:56:02 +00:00
|
|
|
{
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
char buf[384 + REGEXP_CUTOFF];
|
1999-11-04 23:14:30 +00:00
|
|
|
PGresult *res;
|
2000-01-14 22:18:03 +00:00
|
|
|
printQueryOpt myopt = pset.popt;
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* we skip in/out funcs by excluding functions that take some
|
|
|
|
* arguments, but have no types defined for those arguments
|
|
|
|
*/
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf, sizeof(buf),
|
|
|
|
"SELECT format_type(p.prorettype, NULL) as \"%s\",\n"
|
|
|
|
" p.proname as \"%s\",\n"
|
|
|
|
" oidvectortypes(p.proargtypes) as \"%s\"",
|
|
|
|
_("Result data type"), _("Name"),
|
|
|
|
_("Argument data types") );
|
|
|
|
|
2000-04-12 17:17:23 +00:00
|
|
|
if (verbose)
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
|
|
|
",\n u.usename as \"%s\",\n"
|
|
|
|
" l.lanname as \"%s\",\n"
|
|
|
|
" p.prosrc as \"%s\",\n"
|
2001-08-10 18:57:42 +00:00
|
|
|
" obj_description(p.oid, 'pg_proc') as \"%s\"",
|
2001-06-30 17:26:12 +00:00
|
|
|
_("Owner"), _("Language"),
|
|
|
|
_("Source code"), _("Description") );
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
|
2000-04-12 17:17:23 +00:00
|
|
|
if (!verbose)
|
|
|
|
strcat(buf,
|
2000-07-09 21:30:21 +00:00
|
|
|
"\nFROM pg_proc p\n"
|
2001-06-30 17:26:12 +00:00
|
|
|
"WHERE p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '')\n");
|
2000-04-12 17:17:23 +00:00
|
|
|
else
|
|
|
|
strcat(buf,
|
2000-07-09 21:30:21 +00:00
|
|
|
"\nFROM pg_proc p, pg_language l, pg_user u\n"
|
|
|
|
"WHERE p.prolang = l.oid AND p.proowner = u.usesysid\n"
|
2001-06-30 17:26:12 +00:00
|
|
|
" AND p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '')\n");
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
if (name)
|
|
|
|
{
|
2000-04-16 15:46:40 +00:00
|
|
|
strcat(buf, " AND p.proname ~ '^");
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
strncat(buf, name, REGEXP_CUTOFF);
|
|
|
|
strcat(buf, "'\n");
|
1999-11-04 23:14:30 +00:00
|
|
|
}
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "ORDER BY 2, 1, 3;");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
res = PSQLexec(buf);
|
1999-11-04 23:14:30 +00:00
|
|
|
if (!res)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
myopt.nullPrint = NULL;
|
2001-06-30 17:26:12 +00:00
|
|
|
myopt.title = _("List of functions");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
printQuery(res, &myopt, pset.queryFout);
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
PQclear(res);
|
|
|
|
return true;
|
1999-11-04 21:56:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
* \dT
|
|
|
|
* describe types
|
1999-11-04 21:56:02 +00:00
|
|
|
*/
|
|
|
|
bool
|
2000-01-14 22:18:03 +00:00
|
|
|
describeTypes(const char *name, bool verbose)
|
1999-11-04 21:56:02 +00:00
|
|
|
{
|
2000-07-07 19:24:43 +00:00
|
|
|
char buf[384 + 2 * REGEXP_CUTOFF];
|
1999-11-04 23:14:30 +00:00
|
|
|
PGresult *res;
|
2000-01-14 22:18:03 +00:00
|
|
|
printQueryOpt myopt = pset.popt;
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf, sizeof(buf),
|
|
|
|
"SELECT format_type(t.oid, NULL) AS \"%s\",\n",
|
|
|
|
_("Name") );
|
2000-04-12 17:17:23 +00:00
|
|
|
if (verbose)
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
|
|
|
" t.typname AS \"%s\",\n"
|
|
|
|
" CASE WHEN t.typlen = -1\n"
|
|
|
|
" THEN CAST('var' AS text)\n"
|
|
|
|
" ELSE CAST(t.typlen AS text)\n"
|
|
|
|
" END AS \"%s\",\n",
|
|
|
|
_("Internal name"), _("Size") );
|
|
|
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
2001-08-10 18:57:42 +00:00
|
|
|
" obj_description(t.oid, 'pg_type') as \"%s\"\n",
|
2001-06-30 17:26:12 +00:00
|
|
|
_("Description") );
|
2000-04-12 17:17:23 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* do not include array types (start with underscore), do not include
|
|
|
|
* user relations (typrelid!=0)
|
|
|
|
*/
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "FROM pg_type t\nWHERE t.typrelid = 0 AND t.typname !~ '^_.*'\n");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
if (name)
|
|
|
|
{
|
2000-07-07 19:24:43 +00:00
|
|
|
/* accept either internal or external type name */
|
|
|
|
strcat(buf, " AND (format_type(t.oid, NULL) ~ '^");
|
|
|
|
strncat(buf, name, REGEXP_CUTOFF);
|
|
|
|
strcat(buf, "' OR t.typname ~ '^");
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
strncat(buf, name, REGEXP_CUTOFF);
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "')\n");
|
1999-11-04 23:14:30 +00:00
|
|
|
}
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "ORDER BY 1;");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
res = PSQLexec(buf);
|
1999-11-04 23:14:30 +00:00
|
|
|
if (!res)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
myopt.nullPrint = NULL;
|
2001-06-30 17:26:12 +00:00
|
|
|
myopt.title = _("List of data types");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
printQuery(res, &myopt, pset.queryFout);
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
PQclear(res);
|
|
|
|
return true;
|
1999-11-04 21:56:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* \do
|
|
|
|
*/
|
|
|
|
bool
|
2000-01-14 22:18:03 +00:00
|
|
|
describeOperators(const char *name)
|
1999-11-04 21:56:02 +00:00
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
char buf[384 + REGEXP_CUTOFF];
|
1999-11-04 23:14:30 +00:00
|
|
|
PGresult *res;
|
2000-01-14 22:18:03 +00:00
|
|
|
printQueryOpt myopt = pset.popt;
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf, sizeof(buf),
|
|
|
|
"SELECT o.oprname AS \"%s\",\n"
|
|
|
|
" CASE WHEN o.oprkind='l' THEN NULL ELSE format_type(o.oprleft, NULL) END AS \"%s\",\n"
|
|
|
|
" CASE WHEN o.oprkind='r' THEN NULL ELSE format_type(o.oprright, NULL) END AS \"%s\",\n"
|
|
|
|
" format_type(p.prorettype, NULL) AS \"%s\",\n"
|
2001-08-10 18:57:42 +00:00
|
|
|
" obj_description(p.oid, 'pg_proc') as \"%s\"\n"
|
2001-06-30 17:26:12 +00:00
|
|
|
"FROM pg_proc p, pg_operator o\n"
|
|
|
|
"WHERE RegprocToOid(o.oprcode) = p.oid\n",
|
|
|
|
_("Name"), _("Left arg type"), _("Right arg type"),
|
|
|
|
_("Result type"), _("Description") );
|
1999-11-04 23:14:30 +00:00
|
|
|
if (name)
|
|
|
|
{
|
2000-04-16 15:46:40 +00:00
|
|
|
strcat(buf, " AND o.oprname = '");
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
strncat(buf, name, REGEXP_CUTOFF);
|
|
|
|
strcat(buf, "'\n");
|
1999-11-04 23:14:30 +00:00
|
|
|
}
|
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "ORDER BY 1, 2, 3, 4;");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
res = PSQLexec(buf);
|
1999-11-04 23:14:30 +00:00
|
|
|
if (!res)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
myopt.nullPrint = NULL;
|
2001-06-30 17:26:12 +00:00
|
|
|
myopt.title = _("List of operators");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
printQuery(res, &myopt, pset.queryFout);
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
PQclear(res);
|
|
|
|
return true;
|
1999-11-04 21:56:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* listAllDbs
|
|
|
|
*
|
|
|
|
* for \l, \list, and -l switch
|
|
|
|
*/
|
|
|
|
bool
|
2000-01-14 22:18:03 +00:00
|
|
|
listAllDbs(bool desc)
|
1999-11-04 21:56:02 +00:00
|
|
|
{
|
1999-11-04 23:14:30 +00:00
|
|
|
PGresult *res;
|
2000-09-07 04:55:27 +00:00
|
|
|
char buf[1024];
|
2000-01-14 22:18:03 +00:00
|
|
|
printQueryOpt myopt = pset.popt;
|
1999-11-04 21:56:02 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf, sizeof(buf),
|
|
|
|
"SELECT d.datname as \"%s\",\n"
|
|
|
|
" u.usename as \"%s\"",
|
|
|
|
_("Name"), _("Owner"));
|
1999-11-04 21:56:02 +00:00
|
|
|
#ifdef MULTIBYTE
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
|
|
|
",\n pg_encoding_to_char(d.encoding) as \"%s\"",
|
|
|
|
_("Encoding"));
|
1999-11-04 21:56:02 +00:00
|
|
|
#endif
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
if (desc)
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
2001-08-10 18:57:42 +00:00
|
|
|
",\n obj_description(d.oid, 'pg_database') as \"%s\"",
|
2001-06-30 17:26:12 +00:00
|
|
|
_("Description"));
|
2000-01-12 19:36:36 +00:00
|
|
|
strcat(buf,
|
2001-06-30 17:26:12 +00:00
|
|
|
"\nFROM pg_database d LEFT JOIN pg_user u ON d.datdba = u.usesysid\n"
|
|
|
|
"ORDER BY 1;");
|
1999-11-04 21:56:02 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
res = PSQLexec(buf);
|
1999-11-04 23:14:30 +00:00
|
|
|
if (!res)
|
|
|
|
return false;
|
1999-11-04 21:56:02 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
myopt.nullPrint = NULL;
|
2001-06-30 17:26:12 +00:00
|
|
|
myopt.title = _("List of databases");
|
1999-11-04 21:56:02 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
printQuery(res, &myopt, pset.queryFout);
|
1999-11-04 21:56:02 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
PQclear(res);
|
|
|
|
return true;
|
1999-11-04 21:56:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
/*
|
|
|
|
* List Tables Grant/Revoke Permissions
|
1999-11-04 21:56:02 +00:00
|
|
|
* \z (now also \dp -- perhaps more mnemonic)
|
|
|
|
*/
|
|
|
|
bool
|
2000-01-14 22:18:03 +00:00
|
|
|
permissionsList(const char *name)
|
1999-11-04 21:56:02 +00:00
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
char buf[256 + REGEXP_CUTOFF];
|
1999-11-04 23:14:30 +00:00
|
|
|
PGresult *res;
|
2000-01-14 22:18:03 +00:00
|
|
|
printQueryOpt myopt = pset.popt;
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
/* Currently, we ignore indexes since they have no meaningful rights */
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf, sizeof(buf),
|
|
|
|
"SELECT relname as \"%s\",\n"
|
|
|
|
" relacl as \"%s\"\n"
|
|
|
|
"FROM pg_class\n"
|
|
|
|
"WHERE relkind in ('r', 'v', 'S') AND\n"
|
|
|
|
" relname NOT LIKE 'pg$_%%' ESCAPE '$'\n",
|
|
|
|
_("Table"), _("Access privileges"));
|
1999-11-04 23:14:30 +00:00
|
|
|
if (name)
|
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, " AND relname ~ '^");
|
|
|
|
strncat(buf, name, REGEXP_CUTOFF);
|
|
|
|
strcat(buf, "'\n");
|
1999-11-04 23:14:30 +00:00
|
|
|
}
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "ORDER BY 1;");
|
1999-11-04 21:56:02 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
res = PSQLexec(buf);
|
1999-11-04 23:14:30 +00:00
|
|
|
if (!res)
|
|
|
|
return false;
|
|
|
|
|
2000-04-12 17:17:23 +00:00
|
|
|
myopt.nullPrint = NULL;
|
2001-06-30 17:26:12 +00:00
|
|
|
sprintf(buf, _("Access privileges for database \"%s\""), PQdb(pset.db));
|
|
|
|
myopt.title = buf;
|
1999-11-04 21:56:02 +00:00
|
|
|
|
2000-04-12 17:17:23 +00:00
|
|
|
printQuery(res, &myopt, pset.queryFout);
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
PQclear(res);
|
|
|
|
return true;
|
1999-11-04 21:56:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get object comments
|
|
|
|
*
|
|
|
|
* \dd [foo]
|
|
|
|
*
|
|
|
|
* Note: This only lists things that actually have a description. For complete
|
|
|
|
* lists of things, there are other \d? commands.
|
|
|
|
*/
|
|
|
|
bool
|
2000-01-14 22:18:03 +00:00
|
|
|
objectDescription(const char *object)
|
1999-11-04 21:56:02 +00:00
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
char descbuf[2048 + REGEXP_CUTOFF];
|
1999-11-04 23:14:30 +00:00
|
|
|
PGresult *res;
|
2000-01-14 22:18:03 +00:00
|
|
|
printQueryOpt myopt = pset.popt;
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(descbuf, sizeof(descbuf),
|
|
|
|
"SELECT DISTINCT tt.name AS \"%s\", tt.object AS \"%s\", d.description AS \"%s\"\n"
|
|
|
|
"FROM (\n"
|
|
|
|
|
|
|
|
/* Aggregate descriptions */
|
2001-08-10 18:57:42 +00:00
|
|
|
" SELECT a.oid as oid, a.tableoid as tableoid,\n"
|
|
|
|
" CAST(a.aggname AS text) as name, CAST('%s' AS text) as object\n"
|
2001-06-30 17:26:12 +00:00
|
|
|
" FROM pg_aggregate a\n"
|
|
|
|
|
|
|
|
/* Function descriptions (except in/outs for datatypes) */
|
|
|
|
"UNION ALL\n"
|
2001-08-10 18:57:42 +00:00
|
|
|
" SELECT p.oid as oid, p.tableoid as tableoid,\n"
|
|
|
|
" CAST(p.proname AS text) as name, CAST('%s' AS text) as object\n"
|
2001-06-30 17:26:12 +00:00
|
|
|
" FROM pg_proc p\n"
|
|
|
|
" WHERE p.pronargs = 0 or oidvectortypes(p.proargtypes) <> ''\n"
|
|
|
|
|
|
|
|
/* Operator descriptions (must get comment via associated function) */
|
|
|
|
"UNION ALL\n"
|
2001-08-10 18:57:42 +00:00
|
|
|
" SELECT RegprocToOid(o.oprcode) as oid,\n"
|
|
|
|
" (SELECT oid FROM pg_class WHERE relname = 'pg_proc') as tableoid,\n"
|
|
|
|
" CAST(o.oprname AS text) as name, CAST('%s' AS text) as object\n"
|
2001-06-30 17:26:12 +00:00
|
|
|
" FROM pg_operator o\n"
|
|
|
|
|
|
|
|
/* Type description */
|
|
|
|
"UNION ALL\n"
|
2001-08-10 18:57:42 +00:00
|
|
|
" SELECT t.oid as oid, t.tableoid as tableoid,\n"
|
|
|
|
" format_type(t.oid, NULL) as name, CAST('%s' AS text) as object\n"
|
2001-06-30 17:26:12 +00:00
|
|
|
" FROM pg_type t\n"
|
|
|
|
|
|
|
|
/* Relation (tables, views, indexes, sequences) descriptions */
|
|
|
|
"UNION ALL\n"
|
2001-08-10 18:57:42 +00:00
|
|
|
" SELECT c.oid as oid, c.tableoid as tableoid,\n"
|
|
|
|
" CAST(c.relname AS text) as name,\n"
|
2001-06-30 17:26:12 +00:00
|
|
|
" CAST(\n"
|
|
|
|
" CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'i' THEN '%s' WHEN 'S' THEN '%s' END"
|
|
|
|
" AS text) as object\n"
|
|
|
|
" FROM pg_class c\n"
|
|
|
|
|
|
|
|
/* Rule description (ignore rules for views) */
|
|
|
|
"UNION ALL\n"
|
2001-08-10 18:57:42 +00:00
|
|
|
" SELECT r.oid as oid, r.tableoid as tableoid,\n"
|
|
|
|
" CAST(r.rulename AS text) as name, CAST('%s' AS text) as object\n"
|
2001-06-30 17:26:12 +00:00
|
|
|
" FROM pg_rewrite r\n"
|
|
|
|
" WHERE r.rulename !~ '^_RET'\n"
|
|
|
|
|
|
|
|
/* Trigger description */
|
|
|
|
"UNION ALL\n"
|
2001-08-10 18:57:42 +00:00
|
|
|
" SELECT t.oid as oid, t.tableoid as tableoid,\n"
|
|
|
|
" CAST(t.tgname AS text) as name, CAST('%s' AS text) as object\n"
|
2001-06-30 17:26:12 +00:00
|
|
|
" FROM pg_trigger t\n"
|
|
|
|
|
|
|
|
") AS tt,\n"
|
|
|
|
"pg_description d\n"
|
2001-08-10 18:57:42 +00:00
|
|
|
"WHERE tt.oid = d.objoid and tt.tableoid = d.classoid and d.objsubid = 0\n",
|
2001-06-30 17:26:12 +00:00
|
|
|
|
|
|
|
_("Name"), _("Object"), _("Description"),
|
|
|
|
_("aggregate"), _("function"), _("operator"),
|
|
|
|
_("data type"), _("table"), _("view"),
|
|
|
|
_("index"), _("sequence"), _("rule"),
|
|
|
|
_("trigger")
|
|
|
|
);
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
if (object)
|
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(descbuf, " AND tt.name ~ '^");
|
1999-11-04 23:14:30 +00:00
|
|
|
strncat(descbuf, object, REGEXP_CUTOFF);
|
|
|
|
strcat(descbuf, "'\n");
|
|
|
|
}
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(descbuf, "ORDER BY 1;");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
res = PSQLexec(descbuf);
|
1999-11-04 23:14:30 +00:00
|
|
|
if (!res)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
myopt.nullPrint = NULL;
|
2001-06-30 17:26:12 +00:00
|
|
|
myopt.title = _("Object descriptions");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
printQuery(res, &myopt, pset.queryFout);
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
PQclear(res);
|
|
|
|
return true;
|
1999-11-04 21:56:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* describeTableDetails (for \d)
|
|
|
|
*
|
2000-01-12 19:36:36 +00:00
|
|
|
* Unfortunately, the information presented here is so complicated that it cannot
|
1999-11-04 21:56:02 +00:00
|
|
|
* be done in a single query. So we have to assemble the printed table by hand
|
|
|
|
* and pass it to the underlying printTable() function.
|
|
|
|
*
|
|
|
|
*/
|
2000-01-12 19:36:36 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
static void *
|
|
|
|
xmalloc(size_t size)
|
1999-11-04 21:56:02 +00:00
|
|
|
{
|
1999-11-04 23:14:30 +00:00
|
|
|
void *tmp;
|
|
|
|
|
|
|
|
tmp = malloc(size);
|
|
|
|
if (!tmp)
|
|
|
|
{
|
2000-02-07 23:10:11 +00:00
|
|
|
psql_error("out of memory\n");
|
1999-11-04 23:14:30 +00:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
return tmp;
|
1999-11-04 21:56:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2000-01-14 22:18:03 +00:00
|
|
|
describeTableDetails(const char *name, bool desc)
|
1999-11-04 21:56:02 +00:00
|
|
|
{
|
2000-01-10 05:20:26 +00:00
|
|
|
char buf[512 + INDEX_MAX_KEYS * NAMEDATALEN];
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
PGresult *res = NULL;
|
2000-01-14 22:18:03 +00:00
|
|
|
printTableOpt myopt = pset.popt.topt;
|
1999-11-04 23:14:30 +00:00
|
|
|
int i;
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
const char *view_def = NULL;
|
In the spirit of TODO item
* Add use of 'const' for varibles in source tree
(which is misspelled, btw.)
I went through the front-end libpq code and did so. This affects in
particular the various accessor functions (such as PQdb() and
PQgetvalue()) as well as, by necessity, the internal helpers they use.
I have been really thorough in that regard, perhaps some people will find
it annoying that things like
char * foo = PQgetvalue(res, 0, 0)
will generate a warning. On the other hand it _should_ generate one. This
is no real compatibility break, although a few clients will have to be
fixed to suppress warnings. (Which again would be in the spirit of the
above TODO.)
In addition I replaced some int's by size_t's and removed some warnings
(and generated some new ones -- grmpf!). Also I rewrote PQoidStatus (so it
actually honors the const!) and supplied a new function PQoidValue that
returns a proper Oid type. This is only front-end stuff, none of the
communicaton stuff was touched.
The psql patch also adds some new consts to honor the new libpq situation,
as well as fixes a fatal condition that resulted when using the -V
(--version) option and there is no database listening.
So, to summarize, the psql you should definitely put in (with or without
the libpq). If you think I went too far with the const-mania in libpq, let
me know and I'll make adjustments. If you approve it, I will also update
the docs.
-Peter
--
Peter Eisentraut Sernanders vaeg 10:115
1999-11-11 00:10:14 +00:00
|
|
|
const char *headers[5];
|
1999-11-04 23:14:30 +00:00
|
|
|
char **cells = NULL;
|
|
|
|
char *title = NULL;
|
|
|
|
char **footers = NULL;
|
|
|
|
char **ptr;
|
|
|
|
unsigned int cols;
|
2000-04-12 17:17:23 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
bool hasindex;
|
|
|
|
char relkind;
|
|
|
|
int16 checks;
|
|
|
|
int16 triggers;
|
|
|
|
bool hasrules;
|
|
|
|
} tableinfo;
|
|
|
|
bool error = false;
|
|
|
|
|
|
|
|
/* truncate table name */
|
|
|
|
if (strlen(name) > NAMEDATALEN)
|
|
|
|
{
|
|
|
|
char *my_name = xmalloc(NAMEDATALEN + 1);
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2000-04-12 17:17:23 +00:00
|
|
|
strncpy(my_name, name, NAMEDATALEN);
|
|
|
|
my_name[NAMEDATALEN] = '\0';
|
|
|
|
name = my_name;
|
|
|
|
}
|
1999-11-04 21:56:02 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
/* Get general table info */
|
2000-04-12 17:17:23 +00:00
|
|
|
sprintf(buf,
|
|
|
|
"SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules\n"
|
|
|
|
"FROM pg_class WHERE relname='%s'",
|
|
|
|
name);
|
|
|
|
res = PSQLexec(buf);
|
|
|
|
if (!res)
|
|
|
|
return false;
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
/* Did we get anything? */
|
|
|
|
if (PQntuples(res) == 0)
|
|
|
|
{
|
2000-01-14 22:18:03 +00:00
|
|
|
if (!QUIET())
|
2001-06-30 17:26:12 +00:00
|
|
|
fprintf(stderr, _("Did not find any relation named \"%s\".\n"), name);
|
1999-11-04 23:14:30 +00:00
|
|
|
PQclear(res);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2000-04-12 17:17:23 +00:00
|
|
|
/* FIXME: check for null pointers here? */
|
|
|
|
tableinfo.hasindex = strcmp(PQgetvalue(res, 0, 0), "t") == 0;
|
|
|
|
tableinfo.relkind = *(PQgetvalue(res, 0, 1));
|
|
|
|
tableinfo.checks = atoi(PQgetvalue(res, 0, 2));
|
|
|
|
tableinfo.triggers = atoi(PQgetvalue(res, 0, 3));
|
|
|
|
tableinfo.hasrules = strcmp(PQgetvalue(res, 0, 4), "t") == 0;
|
|
|
|
PQclear(res);
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
headers[0] = _("Column");
|
|
|
|
headers[1] = _("Type");
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
cols = 2;
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2000-10-25 20:36:52 +00:00
|
|
|
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
|
|
|
cols++;
|
2001-06-30 17:26:12 +00:00
|
|
|
headers[cols - 1] = _("Modifiers");
|
2000-04-12 17:17:23 +00:00
|
|
|
}
|
1999-11-04 23:14:30 +00:00
|
|
|
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
if (desc)
|
1999-11-04 23:14:30 +00:00
|
|
|
{
|
2000-04-12 17:17:23 +00:00
|
|
|
cols++;
|
2001-06-30 17:26:12 +00:00
|
|
|
headers[cols - 1] = _("Description");
|
1999-11-04 23:14:30 +00:00
|
|
|
}
|
|
|
|
|
2000-04-12 17:17:23 +00:00
|
|
|
headers[cols] = NULL;
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
|
|
|
|
|
2000-04-12 17:17:23 +00:00
|
|
|
/* Get column info */
|
2000-07-07 19:24:43 +00:00
|
|
|
strcpy(buf, "SELECT a.attname, format_type(a.atttypid, a.atttypmod), a.attnotnull, a.atthasdef, a.attnum");
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
if (desc)
|
2001-08-10 18:57:42 +00:00
|
|
|
strcat(buf, ", col_description(a.attrelid, a.attnum)");
|
2000-07-07 19:24:43 +00:00
|
|
|
strcat(buf, "\nFROM pg_class c, pg_attribute a\n"
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
"WHERE c.relname = '");
|
|
|
|
strncat(buf, name, NAMEDATALEN);
|
2000-07-07 19:24:43 +00:00
|
|
|
strcat(buf, "'\n AND a.attnum > 0 AND a.attrelid = c.oid\n"
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
"ORDER BY a.attnum");
|
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
res = PSQLexec(buf);
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
if (!res)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* Check if table is a view */
|
2000-04-12 17:17:23 +00:00
|
|
|
if (tableinfo.hasrules)
|
|
|
|
{
|
|
|
|
PGresult *result;
|
|
|
|
|
|
|
|
sprintf(buf, "SELECT definition FROM pg_views WHERE viewname = '%s'", name);
|
|
|
|
result = PSQLexec(buf);
|
|
|
|
if (!result)
|
|
|
|
{
|
|
|
|
PQclear(res);
|
|
|
|
PQclear(result);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PQntuples(result) > 0)
|
|
|
|
view_def = xstrdup(PQgetvalue(result, 0, 0));
|
|
|
|
PQclear(result);
|
|
|
|
}
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Generate table cells to be printed */
|
|
|
|
cells = xmalloc((PQntuples(res) * cols + 1) * sizeof(*cells));
|
2000-04-12 17:17:23 +00:00
|
|
|
cells[PQntuples(res) * cols] = NULL; /* end of list */
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
for (i = 0; i < PQntuples(res); i++)
|
|
|
|
{
|
|
|
|
/* Name */
|
2000-04-12 17:17:23 +00:00
|
|
|
cells[i * cols + 0] = PQgetvalue(res, i, 0); /* don't free this
|
|
|
|
* afterwards */
|
1999-11-04 23:14:30 +00:00
|
|
|
/* Type */
|
2000-07-07 19:24:43 +00:00
|
|
|
cells[i * cols + 1] = PQgetvalue(res, i, 1); /* don't free this
|
2001-03-22 04:01:46 +00:00
|
|
|
* either */
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
|
|
|
|
/* Extra: not null and default */
|
|
|
|
/* (I'm cutting off the 'default' string at 128) */
|
2000-10-25 20:36:52 +00:00
|
|
|
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
|
|
|
cells[i * cols + 2] = xmalloc(128 + 128);
|
|
|
|
cells[i * cols + 2][0] = '\0';
|
2000-07-07 19:24:43 +00:00
|
|
|
if (strcmp(PQgetvalue(res, i, 2), "t") == 0)
|
2000-04-12 17:17:23 +00:00
|
|
|
strcat(cells[i * cols + 2], "not null");
|
|
|
|
|
|
|
|
/* handle "default" here */
|
2000-07-07 19:24:43 +00:00
|
|
|
if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
|
|
|
PGresult *result;
|
|
|
|
|
|
|
|
sprintf(buf, "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n"
|
|
|
|
"WHERE c.relname = '%s' AND c.oid = d.adrelid AND d.adnum = %s",
|
2000-07-07 19:24:43 +00:00
|
|
|
name, PQgetvalue(res, i, 4));
|
2000-04-12 17:17:23 +00:00
|
|
|
|
|
|
|
result = PSQLexec(buf);
|
|
|
|
if (!result)
|
|
|
|
error = true;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (cells[i * cols + 2][0])
|
|
|
|
strcat(cells[i * cols + 2], " ");
|
|
|
|
strcat(cells[i * cols + 2], "default ");
|
|
|
|
strcat(cells[i * cols + 2], PQgetvalue(result, 0, 0));
|
|
|
|
PQclear(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
/* Description */
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
if (desc)
|
2000-07-07 19:24:43 +00:00
|
|
|
cells[i * cols + cols - 1] = PQgetvalue(res, i, 5);
|
1999-11-04 23:14:30 +00:00
|
|
|
}
|
1999-11-04 21:56:02 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
/* Make title */
|
2001-06-30 17:26:12 +00:00
|
|
|
title = xmalloc(32 + NAMEDATALEN);
|
2000-04-12 17:17:23 +00:00
|
|
|
switch (tableinfo.relkind)
|
|
|
|
{
|
|
|
|
case 'r':
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(title, 32 + NAMEDATALEN, _("Table \"%s\""), name);
|
2000-10-25 20:36:52 +00:00
|
|
|
break;
|
|
|
|
case 'v':
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(title, 32 + NAMEDATALEN, _("View \"%s\""), name);
|
2000-04-12 17:17:23 +00:00
|
|
|
break;
|
|
|
|
case 'S':
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(title, 32 + NAMEDATALEN, _("Sequence \"%s\""), name);
|
2000-04-12 17:17:23 +00:00
|
|
|
break;
|
|
|
|
case 'i':
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(title, 32 + NAMEDATALEN, _("Index \"%s\""), name);
|
2000-04-12 17:17:23 +00:00
|
|
|
break;
|
|
|
|
case 's':
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(title, 32 + NAMEDATALEN, _("Special relation \"%s\""), name);
|
2000-04-12 17:17:23 +00:00
|
|
|
break;
|
2001-08-09 03:32:16 +00:00
|
|
|
case 't':
|
|
|
|
snprintf(title, 32 + NAMEDATALEN, _("TOAST table \"%s\""), name);
|
|
|
|
break;
|
2000-04-12 17:17:23 +00:00
|
|
|
default:
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(title, 32 + NAMEDATALEN, _("?%c? \"%s\""), tableinfo.relkind, name);
|
2000-10-25 20:36:52 +00:00
|
|
|
break;
|
2000-04-12 17:17:23 +00:00
|
|
|
}
|
1999-11-04 23:14:30 +00:00
|
|
|
|
|
|
|
/* Make footers */
|
2000-04-12 17:17:23 +00:00
|
|
|
if (tableinfo.relkind == 'i')
|
|
|
|
{
|
2001-08-05 22:13:46 +00:00
|
|
|
/* Footer information about an index */
|
2000-04-12 17:17:23 +00:00
|
|
|
PGresult *result;
|
|
|
|
|
2001-08-05 22:13:46 +00:00
|
|
|
sprintf(buf, "SELECT i.indisunique, i.indisprimary, i.indislossy, a.amname,\n"
|
|
|
|
" pg_get_expr(i.indpred, i.indrelid) as indpred\n"
|
2000-04-12 17:17:23 +00:00
|
|
|
"FROM pg_index i, pg_class c, pg_am a\n"
|
|
|
|
"WHERE i.indexrelid = c.oid AND c.relname = '%s' AND c.relam = a.oid",
|
|
|
|
name);
|
|
|
|
|
|
|
|
result = PSQLexec(buf);
|
2001-08-05 22:13:46 +00:00
|
|
|
if (!result || PQntuples(result) != 1)
|
2000-04-12 17:17:23 +00:00
|
|
|
error = true;
|
|
|
|
else
|
|
|
|
{
|
2001-08-05 22:13:46 +00:00
|
|
|
char *indisunique = PQgetvalue(result, 0, 0);
|
|
|
|
char *indisprimary = PQgetvalue(result, 0, 1);
|
|
|
|
char *indislossy = PQgetvalue(result, 0, 2);
|
|
|
|
char *indamname = PQgetvalue(result, 0, 3);
|
|
|
|
char *indpred = PQgetvalue(result, 0, 4);
|
|
|
|
|
|
|
|
footers = xmalloc(3 * sizeof(*footers));
|
2001-07-08 14:42:17 +00:00
|
|
|
/* XXX This construction is poorly internationalized. */
|
|
|
|
footers[0] = xmalloc(NAMEDATALEN + 128);
|
2001-08-05 22:13:46 +00:00
|
|
|
snprintf(footers[0], NAMEDATALEN + 128, "%s%s",
|
|
|
|
strcmp(indisunique, "t") == 0 ? _("unique ") : "",
|
|
|
|
indamname);
|
|
|
|
if (strcmp(indisprimary, "t") == 0)
|
2001-07-08 14:42:17 +00:00
|
|
|
snprintf(footers[0] + strlen(footers[0]),
|
|
|
|
NAMEDATALEN + 128 - strlen(footers[0]),
|
|
|
|
_(" (primary key)"));
|
2001-08-05 22:13:46 +00:00
|
|
|
if (strcmp(indislossy, "t") == 0)
|
|
|
|
snprintf(footers[0] + strlen(footers[0]),
|
|
|
|
NAMEDATALEN + 128 - strlen(footers[0]),
|
|
|
|
_(" (lossy)"));
|
|
|
|
if (strlen(indpred) > 0)
|
|
|
|
{
|
|
|
|
footers[1] = xmalloc(64 + strlen(indpred));
|
|
|
|
snprintf(footers[1], 64 + strlen(indpred),
|
|
|
|
_("Index predicate: %s"), indpred);
|
|
|
|
footers[2] = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
footers[1] = NULL;
|
2000-04-12 17:17:23 +00:00
|
|
|
}
|
|
|
|
}
|
2000-10-25 20:36:52 +00:00
|
|
|
else if (view_def)
|
1999-11-04 23:14:30 +00:00
|
|
|
{
|
2001-08-05 22:13:46 +00:00
|
|
|
/* Footer information about a view */
|
1999-11-04 23:14:30 +00:00
|
|
|
footers = xmalloc(2 * sizeof(*footers));
|
2001-06-30 17:26:12 +00:00
|
|
|
footers[0] = xmalloc(64 + strlen(view_def));
|
|
|
|
snprintf(footers[0], 64 + strlen(view_def),
|
|
|
|
_("View definition: %s"), view_def);
|
1999-11-04 23:14:30 +00:00
|
|
|
footers[1] = NULL;
|
|
|
|
}
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
else if (tableinfo.relkind == 'r')
|
1999-11-04 23:14:30 +00:00
|
|
|
{
|
2001-08-05 22:13:46 +00:00
|
|
|
/* Footer information about a table */
|
2001-05-28 02:01:22 +00:00
|
|
|
PGresult *result1 = NULL,
|
|
|
|
*result2 = NULL,
|
|
|
|
*result3 = NULL,
|
|
|
|
*result4 = NULL,
|
|
|
|
*result5 = NULL,
|
|
|
|
*result6 = NULL;
|
2000-04-12 17:17:23 +00:00
|
|
|
int index_count = 0,
|
2001-05-28 02:01:22 +00:00
|
|
|
primary_count = 0,
|
|
|
|
unique_count = 0,
|
|
|
|
constr_count = 0,
|
|
|
|
rule_count = 0,
|
|
|
|
trigger_count = 0;
|
2000-04-12 17:17:23 +00:00
|
|
|
int count_footers = 0;
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
/* count indexes */
|
2000-04-12 17:17:23 +00:00
|
|
|
if (!error && tableinfo.hasindex)
|
|
|
|
{
|
|
|
|
sprintf(buf, "SELECT c2.relname\n"
|
|
|
|
"FROM pg_class c, pg_class c2, pg_index i\n"
|
|
|
|
"WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
|
2001-05-28 02:01:22 +00:00
|
|
|
"AND NOT i.indisunique ORDER BY c2.relname",
|
2000-04-12 17:17:23 +00:00
|
|
|
name);
|
|
|
|
result1 = PSQLexec(buf);
|
|
|
|
if (!result1)
|
|
|
|
error = true;
|
|
|
|
else
|
|
|
|
index_count = PQntuples(result1);
|
|
|
|
}
|
|
|
|
|
2001-05-28 02:01:22 +00:00
|
|
|
/* count primary keys */
|
|
|
|
if (!error && tableinfo.hasindex)
|
|
|
|
{
|
|
|
|
sprintf(buf, "SELECT c2.relname\n"
|
|
|
|
"FROM pg_class c, pg_class c2, pg_index i\n"
|
|
|
|
"WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
|
|
|
|
"AND i.indisprimary AND i.indisunique ORDER BY c2.relname",
|
|
|
|
name);
|
|
|
|
result5 = PSQLexec(buf);
|
|
|
|
if (!result5)
|
|
|
|
error = true;
|
|
|
|
else
|
|
|
|
primary_count = PQntuples(result5);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* count unique constraints */
|
|
|
|
if (!error && tableinfo.hasindex)
|
|
|
|
{
|
|
|
|
sprintf(buf, "SELECT c2.relname\n"
|
|
|
|
"FROM pg_class c, pg_class c2, pg_index i\n"
|
|
|
|
"WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
|
|
|
|
"AND NOT i.indisprimary AND i.indisunique ORDER BY c2.relname",
|
|
|
|
name);
|
|
|
|
result6 = PSQLexec(buf);
|
|
|
|
if (!result6)
|
|
|
|
error = true;
|
|
|
|
else
|
|
|
|
unique_count = PQntuples(result6);
|
|
|
|
}
|
|
|
|
|
2000-04-12 17:17:23 +00:00
|
|
|
/* count table (and column) constraints */
|
|
|
|
if (!error && tableinfo.checks)
|
|
|
|
{
|
2001-05-28 02:01:22 +00:00
|
|
|
sprintf(buf, "SELECT rcsrc, rcname\n"
|
2000-04-12 17:17:23 +00:00
|
|
|
"FROM pg_relcheck r, pg_class c\n"
|
|
|
|
"WHERE c.relname='%s' AND c.oid = r.rcrelid",
|
|
|
|
name);
|
|
|
|
result2 = PSQLexec(buf);
|
|
|
|
if (!result2)
|
|
|
|
error = true;
|
|
|
|
else
|
|
|
|
constr_count = PQntuples(result2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* count rules */
|
|
|
|
if (!error && tableinfo.hasrules)
|
|
|
|
{
|
|
|
|
sprintf(buf,
|
|
|
|
"SELECT r.rulename\n"
|
|
|
|
"FROM pg_rewrite r, pg_class c\n"
|
|
|
|
"WHERE c.relname='%s' AND c.oid = r.ev_class",
|
|
|
|
name);
|
|
|
|
result3 = PSQLexec(buf);
|
|
|
|
if (!result3)
|
|
|
|
error = true;
|
|
|
|
else
|
|
|
|
rule_count = PQntuples(result3);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* count triggers */
|
|
|
|
if (!error && tableinfo.hasrules)
|
|
|
|
{
|
|
|
|
sprintf(buf,
|
|
|
|
"SELECT t.tgname\n"
|
|
|
|
"FROM pg_trigger t, pg_class c\n"
|
|
|
|
"WHERE c.relname='%s' AND c.oid = t.tgrelid",
|
|
|
|
name);
|
|
|
|
result4 = PSQLexec(buf);
|
|
|
|
if (!result4)
|
|
|
|
error = true;
|
|
|
|
else
|
|
|
|
trigger_count = PQntuples(result4);
|
|
|
|
}
|
|
|
|
|
2001-05-28 02:01:22 +00:00
|
|
|
footers = xmalloc((index_count + primary_count + unique_count +
|
|
|
|
constr_count + rule_count + trigger_count + 1)
|
|
|
|
* sizeof(*footers));
|
2000-04-12 17:17:23 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
/* print indexes */
|
2000-04-12 17:17:23 +00:00
|
|
|
for (i = 0; i < index_count; i++)
|
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
char *s = _("Indexes");
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result1, i, 0));
|
|
|
|
else
|
|
|
|
snprintf(buf, sizeof(buf), "%*s %s", (int)strlen(s), "", PQgetvalue(result1, i, 0));
|
2000-04-12 17:17:23 +00:00
|
|
|
if (i < index_count - 1)
|
|
|
|
strcat(buf, ",");
|
|
|
|
|
|
|
|
footers[count_footers++] = xstrdup(buf);
|
|
|
|
}
|
|
|
|
|
2001-05-28 02:01:22 +00:00
|
|
|
/* print primary keys */
|
|
|
|
for (i = 0; i < primary_count; i++)
|
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
char *s = _("Primary key");
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result5, i, 0));
|
|
|
|
else
|
|
|
|
snprintf(buf, sizeof(buf), "%*s %s", (int)strlen(s), "", PQgetvalue(result5, i, 0));
|
2001-05-28 02:01:22 +00:00
|
|
|
if (i < primary_count - 1)
|
|
|
|
strcat(buf, ",");
|
|
|
|
|
|
|
|
footers[count_footers++] = xstrdup(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* print unique constraints */
|
|
|
|
for (i = 0; i < unique_count; i++)
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
char *s = _("Unique keys");
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result6, i, 0));
|
|
|
|
else
|
|
|
|
snprintf(buf, sizeof(buf), "%*s %s", (int)strlen(s), "", PQgetvalue(result6, i, 0));
|
2001-05-28 02:01:22 +00:00
|
|
|
if (i < unique_count - 1)
|
|
|
|
strcat(buf, ",");
|
|
|
|
|
|
|
|
footers[count_footers++] = xstrdup(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* print constraints */
|
|
|
|
for (i = 0; i < constr_count; i++)
|
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
char *s = _("Check constraints");
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
snprintf(buf, sizeof(buf), _("%s: \"%s\" %s"), s,
|
|
|
|
PQgetvalue(result2, i, 1), PQgetvalue(result2, i, 0));
|
|
|
|
else
|
|
|
|
snprintf(buf, sizeof(buf), _("%*s \"%s\" %s"), (int)strlen(s), "",
|
|
|
|
PQgetvalue(result2, i, 1), PQgetvalue(result2, i, 0));
|
2000-04-12 17:17:23 +00:00
|
|
|
footers[count_footers++] = xstrdup(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* print rules */
|
|
|
|
for (i = 0; i < rule_count; i++)
|
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
char *s = _("Rules");
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result3, i, 0));
|
|
|
|
else
|
|
|
|
snprintf(buf, sizeof(buf), "%*s %s", (int)strlen(s), "", PQgetvalue(result3, i, 0));
|
2000-04-12 17:17:23 +00:00
|
|
|
if (i < rule_count - 1)
|
|
|
|
strcat(buf, ",");
|
|
|
|
|
|
|
|
footers[count_footers++] = xstrdup(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* print triggers */
|
|
|
|
for (i = 0; i < trigger_count; i++)
|
|
|
|
{
|
2001-06-30 17:26:12 +00:00
|
|
|
char *s = _("Triggers");
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result4, i, 0));
|
|
|
|
else
|
|
|
|
snprintf(buf, sizeof(buf), "%*s %s", (int)strlen(s), "", PQgetvalue(result4, i, 0));
|
2000-04-12 17:17:23 +00:00
|
|
|
if (i < trigger_count - 1)
|
|
|
|
strcat(buf, ",");
|
|
|
|
|
|
|
|
footers[count_footers++] = xstrdup(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* end of list marker */
|
|
|
|
footers[count_footers] = NULL;
|
|
|
|
|
|
|
|
PQclear(result1);
|
|
|
|
PQclear(result2);
|
|
|
|
PQclear(result3);
|
|
|
|
PQclear(result4);
|
2001-05-28 02:01:22 +00:00
|
|
|
PQclear(result5);
|
|
|
|
PQclear(result6);
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
}
|
1999-11-04 21:56:02 +00:00
|
|
|
|
2000-04-12 17:17:23 +00:00
|
|
|
if (!error)
|
|
|
|
printTable(title, headers,
|
|
|
|
(const char **) cells, (const char **) footers,
|
|
|
|
"llll", &myopt, pset.queryFout);
|
1999-11-04 21:56:02 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
/* clean up */
|
|
|
|
free(title);
|
1999-11-04 21:56:02 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
for (i = 0; i < PQntuples(res); i++)
|
|
|
|
{
|
2000-10-25 20:36:52 +00:00
|
|
|
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')
|
2000-04-12 17:17:23 +00:00
|
|
|
free(cells[i * cols + 2]);
|
1999-11-04 23:14:30 +00:00
|
|
|
}
|
|
|
|
free(cells);
|
1999-11-04 21:56:02 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
for (ptr = footers; footers && *ptr; ptr++)
|
|
|
|
free(*ptr);
|
|
|
|
free(footers);
|
1999-11-04 21:56:02 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
PQclear(res);
|
1999-11-04 21:56:02 +00:00
|
|
|
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
return !error;
|
1999-11-04 21:56:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-05-09 17:29:10 +00:00
|
|
|
/*
|
|
|
|
* \du [user]
|
|
|
|
*
|
|
|
|
* Describes users, possibly based on a simplistic prefix search on the
|
|
|
|
* argument.
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool
|
|
|
|
describeUsers (const char *name)
|
|
|
|
{
|
|
|
|
char buf[384 + REGEXP_CUTOFF];
|
|
|
|
PGresult *res;
|
2001-06-30 17:26:12 +00:00
|
|
|
printQueryOpt myopt = pset.popt;
|
2001-05-09 17:29:10 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf, sizeof(buf),
|
|
|
|
"SELECT u.usename AS \"%s\",\n"
|
|
|
|
" u.usesysid AS \"%s\",\n"
|
|
|
|
" CASE WHEN u.usesuper AND u.usecreatedb THEN CAST('%s' AS text)\n"
|
|
|
|
" WHEN u.usesuper THEN CAST('%s' AS text)\n"
|
|
|
|
" WHEN u.usecreatedb THEN CAST('%s' AS text)\n"
|
|
|
|
" ELSE CAST('' AS text)\n"
|
|
|
|
" END AS \"%s\"\n"
|
|
|
|
"FROM pg_user u\n",
|
|
|
|
_("User name"), _("User ID"),
|
|
|
|
_("superuser, create database"),
|
|
|
|
_("superuser"), _("create database"),
|
|
|
|
_("Attributes") );
|
2001-05-09 17:29:10 +00:00
|
|
|
if (name)
|
|
|
|
{
|
2001-05-27 21:50:50 +00:00
|
|
|
strcat(buf, "WHERE u.usename ~ '^");
|
2001-05-09 17:29:10 +00:00
|
|
|
strncat(buf, name, REGEXP_CUTOFF);
|
|
|
|
strcat(buf, "'\n");
|
|
|
|
}
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "ORDER BY 1;");
|
2001-05-09 17:29:10 +00:00
|
|
|
|
|
|
|
res = PSQLexec(buf);
|
|
|
|
if (!res)
|
|
|
|
return false;
|
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
myopt.nullPrint = NULL;
|
|
|
|
myopt.title = _("List of database users");
|
2001-05-09 17:29:10 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
printQuery(res, &myopt, pset.queryFout);
|
2001-05-09 17:29:10 +00:00
|
|
|
|
|
|
|
PQclear(res);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
1999-11-04 21:56:02 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* listTables()
|
|
|
|
*
|
|
|
|
* handler for \d, \dt, etc.
|
|
|
|
*
|
|
|
|
* The infotype is an array of characters, specifying what info is desired:
|
|
|
|
* t - tables
|
2001-06-30 17:26:12 +00:00
|
|
|
* i - indexes
|
1999-11-04 21:56:02 +00:00
|
|
|
* v - views
|
|
|
|
* s - sequences
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
* S - systems tables (~ '^pg_')
|
1999-11-04 21:56:02 +00:00
|
|
|
* (any order of the above is fine)
|
2000-01-12 19:36:36 +00:00
|
|
|
*
|
|
|
|
* Note: For some reason it always happens to people that their tables have owners
|
|
|
|
* that are no longer in pg_user; consequently they wouldn't show up here. The code
|
|
|
|
* tries to fix this the painful way, hopefully outer joins will be done sometime.
|
1999-11-04 21:56:02 +00:00
|
|
|
*/
|
|
|
|
bool
|
2000-01-14 22:18:03 +00:00
|
|
|
listTables(const char *infotype, const char *name, bool desc)
|
1999-11-04 21:56:02 +00:00
|
|
|
{
|
1999-11-04 23:14:30 +00:00
|
|
|
bool showTables = strchr(infotype, 't') != NULL;
|
2001-06-30 17:26:12 +00:00
|
|
|
bool showIndexes = strchr(infotype, 'i') != NULL;
|
1999-11-04 23:14:30 +00:00
|
|
|
bool showViews = strchr(infotype, 'v') != NULL;
|
|
|
|
bool showSeq = strchr(infotype, 's') != NULL;
|
|
|
|
bool showSystem = strchr(infotype, 'S') != NULL;
|
|
|
|
|
2000-01-12 19:36:36 +00:00
|
|
|
char buf[3072 + 8 * REGEXP_CUTOFF];
|
1999-11-04 23:14:30 +00:00
|
|
|
PGresult *res;
|
2000-01-14 22:18:03 +00:00
|
|
|
printQueryOpt myopt = pset.popt;
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
if (showSystem && !(showSeq || showIndexes || showViews || showTables))
|
2000-04-16 20:04:51 +00:00
|
|
|
showTables = showViews = showSeq = true;
|
|
|
|
|
|
|
|
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 04:24:17 +00:00
|
|
|
buf[0] = '\0';
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
snprintf(buf, sizeof(buf),
|
|
|
|
"SELECT 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"
|
|
|
|
" u.usename as \"%s\"",
|
|
|
|
_("Name"), _("table"), _("view"), _("index"), _("sequence"),
|
|
|
|
_("special"), _("Type"), _("Owner"));
|
2000-01-12 19:36:36 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
if (desc)
|
|
|
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
2001-08-10 18:57:42 +00:00
|
|
|
",\n obj_description(c.oid, 'pg_class') as \"%s\"",
|
2001-06-30 17:26:12 +00:00
|
|
|
_("Description"));
|
|
|
|
strcat(buf,
|
|
|
|
"\nFROM pg_class c LEFT JOIN pg_user u ON c.relowner = u.usesysid\n"
|
|
|
|
"WHERE c.relkind IN (");
|
|
|
|
if (showTables)
|
|
|
|
strcat(buf, "'r',");
|
1999-11-04 23:14:30 +00:00
|
|
|
if (showViews)
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "'v',");
|
|
|
|
if (showIndexes)
|
|
|
|
strcat(buf, "'i',");
|
|
|
|
if (showSeq)
|
|
|
|
strcat(buf, "'S',");
|
1999-11-04 23:14:30 +00:00
|
|
|
if (showSystem && showTables)
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "'s',");
|
|
|
|
strcat(buf, "''"); /* dummy */
|
|
|
|
strcat(buf, ")\n");
|
1999-11-04 23:14:30 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
if (showSystem)
|
|
|
|
strcat(buf, " AND c.relname ~ '^pg_'\n");
|
|
|
|
else
|
|
|
|
strcat(buf, " AND c.relname !~ '^pg_'\n");
|
2000-01-12 19:36:36 +00:00
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
if (name)
|
|
|
|
{
|
|
|
|
strcat(buf, " AND c.relname ~ '^");
|
|
|
|
strncat(buf, name, REGEXP_CUTOFF);
|
|
|
|
strcat(buf, "'\n");
|
1999-11-04 21:56:02 +00:00
|
|
|
}
|
|
|
|
|
2001-06-30 17:26:12 +00:00
|
|
|
strcat(buf, "ORDER BY 1;");
|
1999-11-04 21:56:02 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
res = PSQLexec(buf);
|
1999-11-04 23:14:30 +00:00
|
|
|
if (!res)
|
|
|
|
return false;
|
1999-11-04 21:56:02 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
if (PQntuples(res) == 0 && !QUIET())
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
|
|
|
if (name)
|
2001-06-30 17:26:12 +00:00
|
|
|
fprintf(pset.queryFout, _("No matching relations found.\n"));
|
2000-04-12 17:17:23 +00:00
|
|
|
else
|
2001-06-30 17:26:12 +00:00
|
|
|
fprintf(pset.queryFout, _("No relations found.\n"));
|
2000-04-12 17:17:23 +00:00
|
|
|
}
|
1999-11-04 23:14:30 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
myopt.nullPrint = NULL;
|
2001-06-30 17:26:12 +00:00
|
|
|
myopt.title = _("List of relations");
|
1999-11-04 21:56:02 +00:00
|
|
|
|
2000-01-14 22:18:03 +00:00
|
|
|
printQuery(res, &myopt, pset.queryFout);
|
1999-11-04 23:14:30 +00:00
|
|
|
}
|
1999-11-04 21:56:02 +00:00
|
|
|
|
1999-11-04 23:14:30 +00:00
|
|
|
PQclear(res);
|
|
|
|
return true;
|
1999-11-04 21:56:02 +00:00
|
|
|
}
|