2000-01-19 00:30:24 +01:00
/*
* psql - the PostgreSQL interactive terminal
*
2000-01-29 17:58:54 +01:00
* Copyright 2000 by PostgreSQL Global Development Group
2000-01-19 00:30:24 +01:00
*
2002-05-13 19:45:30 +02:00
* $ Header : / cvsroot / pgsql / src / bin / psql / describe . c , v 1.54 2002 / 05 / 13 17 : 45 : 30 tgl Exp $
2000-01-19 00:30:24 +01:00
*/
2001-02-10 03:31:31 +01:00
# include "postgres_fe.h"
1999-11-04 22:56:02 +01:00
# include "describe.h"
2000-02-16 14:15:26 +01:00
# include "libpq-fe.h"
2002-04-24 07:24:00 +02:00
# include "pqexpbuffer.h"
1999-11-04 22:56:02 +01:00
# include "common.h"
# include "settings.h"
# include "print.h"
# include "variables.h"
2001-06-30 19:26:12 +02:00
# define _(x) gettext((x))
1999-11-04 22:56:02 +01:00
/*----------------
* Handlers for various slash commands displaying some sort of list
* of things in the database .
*
2000-01-12 20:36:36 +01:00
* If you add something here , try to format the query to look nice in - E output .
1999-11-04 22:56:02 +01:00
* - - - - - - - - - - - - - - - -
*/
/* \da
* takes an optional regexp to match specific aggregates by name
*/
bool
2000-01-14 23:18:03 +01:00
describeAggregates ( const char * name )
1999-11-04 22:56:02 +01:00
{
2002-04-24 07:24:00 +02:00
PQExpBufferData buf ;
1999-11-05 00:14:30 +01:00
PGresult * res ;
2000-01-14 23:18:03 +01:00
printQueryOpt myopt = pset . popt ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
initPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
/*
* There are two kinds of aggregates : ones that work on particular
2002-04-11 22:00:18 +02:00
* types and ones that work on all ( denoted by input type = 0 )
1999-11-05 00:14:30 +01:00
*/
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf ,
2002-04-11 22:00:18 +02:00
" SELECT p.proname AS \" %s \" , \n "
" CASE p.proargtypes[0] \n "
2001-06-30 19:26:12 +02:00
" WHEN 0 THEN CAST('%s' AS text) \n "
2002-04-11 22:00:18 +02:00
" ELSE format_type(p.proargtypes[0], NULL) \n "
2001-06-30 19:26:12 +02:00
" END AS \" %s \" , \n "
2002-04-11 22:00:18 +02:00
" obj_description(p.oid, 'pg_proc') as \" %s \" \n "
" FROM pg_proc p \n "
" WHERE p.proisagg \n " ,
2001-06-30 19:26:12 +02:00
_ ( " Name " ) , _ ( " (all types) " ) ,
2001-10-25 07:50:21 +02:00
_ ( " 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 05:24:17 +01:00
1999-11-05 00:14:30 +01:00
if ( name )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " AND p.proname ~ '^%s' \n " , name ) ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " ORDER BY 1, 2; " ) ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
if ( ! res )
return false ;
myopt . nullPrint = NULL ;
2001-06-30 19:26:12 +02:00
myopt . title = _ ( " List of aggregate functions " ) ;
1999-11-05 00:14:30 +01:00
2000-01-14 23:18:03 +01:00
printQuery ( res , & myopt , pset . queryFout ) ;
1999-11-05 00:14:30 +01:00
PQclear ( res ) ;
return true ;
1999-11-04 22:56:02 +01: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 05:24:17 +01:00
* Takes an optional regexp to narrow down the function name
1999-11-04 22:56:02 +01:00
*/
bool
2000-01-14 23:18:03 +01:00
describeFunctions ( const char * name , bool verbose )
1999-11-04 22:56:02 +01:00
{
2002-04-24 07:24:00 +02:00
PQExpBufferData buf ;
1999-11-05 00:14:30 +01:00
PGresult * res ;
2000-01-14 23:18:03 +01:00
printQueryOpt myopt = pset . popt ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
initPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
/*
* we skip in / out funcs by excluding functions that take some
* arguments , but have no types defined for those arguments
*/
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf ,
2001-06-30 19:26:12 +02:00
" SELECT format_type(p.prorettype, NULL) as \" %s \" , \n "
" p.proname as \" %s \" , \n "
" oidvectortypes(p.proargtypes) as \" %s \" " ,
_ ( " Result data type " ) , _ ( " Name " ) ,
2001-10-25 07:50:21 +02:00
_ ( " Argument data types " ) ) ;
2001-06-30 19:26:12 +02:00
2000-04-12 19:17:23 +02:00
if ( verbose )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf ,
2001-06-30 19:26:12 +02:00
" , \n u.usename as \" %s \" , \n "
" l.lanname as \" %s \" , \n "
" p.prosrc as \" %s \" , \n "
2001-08-10 20:57:42 +02:00
" obj_description(p.oid, 'pg_proc') as \" %s \" " ,
2001-06-30 19:26:12 +02:00
_ ( " Owner " ) , _ ( " Language " ) ,
2001-10-25 07:50:21 +02:00
_ ( " 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 05:24:17 +01:00
2000-04-12 19:17:23 +02:00
if ( ! verbose )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf ,
2000-07-09 23:30:21 +02:00
" \n FROM pg_proc p \n "
2002-04-11 22:00:18 +02:00
" WHERE p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg \n " ) ;
2000-04-12 19:17:23 +02:00
else
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf ,
2000-07-09 23:30:21 +02:00
" \n FROM pg_proc p, pg_language l, pg_user u \n "
" WHERE p.prolang = l.oid AND p.proowner = u.usesysid \n "
2002-04-11 22:00:18 +02:00
" AND p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg \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 05:24:17 +01:00
1999-11-05 00:14:30 +01:00
if ( name )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " AND p.proname ~ '^%s' \n " , name ) ;
appendPQExpBuffer ( & buf , " ORDER BY 2, 1, 3; " ) ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
if ( ! res )
return false ;
myopt . nullPrint = NULL ;
2001-06-30 19:26:12 +02:00
myopt . title = _ ( " List of functions " ) ;
1999-11-05 00:14:30 +01:00
2000-01-14 23:18:03 +01:00
printQuery ( res , & myopt , pset . queryFout ) ;
1999-11-05 00:14:30 +01:00
PQclear ( res ) ;
return true ;
1999-11-04 22:56:02 +01: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 05:24:17 +01:00
* \ dT
* describe types
1999-11-04 22:56:02 +01:00
*/
bool
2000-01-14 23:18:03 +01:00
describeTypes ( const char * name , bool verbose )
1999-11-04 22:56:02 +01:00
{
2002-04-24 07:24:00 +02:00
PQExpBufferData buf ;
1999-11-05 00:14:30 +01:00
PGresult * res ;
2000-01-14 23:18:03 +01:00
printQueryOpt myopt = pset . popt ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
initPQExpBuffer ( & buf ) ;
printfPQExpBuffer ( & buf ,
2001-06-30 19:26:12 +02:00
" SELECT format_type(t.oid, NULL) AS \" %s \" , \n " ,
2001-10-25 07:50:21 +02:00
_ ( " Name " ) ) ;
2000-04-12 19:17:23 +02:00
if ( verbose )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf ,
2001-06-30 19:26:12 +02:00
" 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 " ,
2001-10-25 07:50:21 +02:00
_ ( " Internal name " ) , _ ( " Size " ) ) ;
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf ,
2001-08-10 20:57:42 +02:00
" obj_description(t.oid, 'pg_type') as \" %s \" \n " ,
2001-10-25 07:50:21 +02:00
_ ( " Description " ) ) ;
2000-04-12 19:17:23 +02:00
/*
* do not include array types ( start with underscore ) , do not include
* user relations ( typrelid ! = 0 )
*/
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " FROM pg_type t \n WHERE t.typrelid = 0 AND t.typname !~ '^_.*' \n " ) ;
1999-11-05 00:14:30 +01:00
if ( name )
2000-07-07 21:24:43 +02:00
/* accept either internal or external type name */
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " AND (format_type(t.oid, NULL) ~ '^%s' OR t.typname ~ '^%s') \n " , name , name ) ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " ORDER BY 1; " ) ;
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
if ( ! res )
return false ;
myopt . nullPrint = NULL ;
2001-06-30 19:26:12 +02:00
myopt . title = _ ( " List of data types " ) ;
1999-11-05 00:14:30 +01:00
2000-01-14 23:18:03 +01:00
printQuery ( res , & myopt , pset . queryFout ) ;
1999-11-05 00:14:30 +01:00
PQclear ( res ) ;
return true ;
1999-11-04 22:56:02 +01:00
}
/* \do
*/
bool
2000-01-14 23:18:03 +01:00
describeOperators ( const char * name )
1999-11-04 22:56:02 +01:00
{
2002-04-24 07:24:00 +02:00
PQExpBufferData buf ;
1999-11-05 00:14:30 +01:00
PGresult * res ;
2000-01-14 23:18:03 +01:00
printQueryOpt myopt = pset . popt ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
initPQExpBuffer ( & buf ) ;
printfPQExpBuffer ( & buf ,
2001-06-30 19:26:12 +02:00
" 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 "
2001-11-12 16:57:08 +01:00
" format_type(o.oprresult, NULL) AS \" %s \" , \n "
2002-05-13 19:45:30 +02:00
" coalesce(obj_description(o.oid, 'pg_operator'), "
" obj_description(o.oprcode, 'pg_proc')) AS \" %s \" \n "
2001-11-12 16:57:08 +01:00
" FROM pg_operator o \n " ,
2001-06-30 19:26:12 +02:00
_ ( " Name " ) , _ ( " Left arg type " ) , _ ( " Right arg type " ) ,
2001-10-25 07:50:21 +02:00
_ ( " Result type " ) , _ ( " Description " ) ) ;
1999-11-05 00:14:30 +01:00
if ( name )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " WHERE o.oprname = '%s' \n " , name ) ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " ORDER BY 1, 2, 3, 4; " ) ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
if ( ! res )
return false ;
myopt . nullPrint = NULL ;
2001-06-30 19:26:12 +02:00
myopt . title = _ ( " List of operators " ) ;
1999-11-05 00:14:30 +01:00
2000-01-14 23:18:03 +01:00
printQuery ( res , & myopt , pset . queryFout ) ;
1999-11-05 00:14:30 +01:00
PQclear ( res ) ;
return true ;
1999-11-04 22:56:02 +01:00
}
/*
* listAllDbs
*
* for \ l , \ list , and - l switch
*/
bool
2000-01-14 23:18:03 +01:00
listAllDbs ( bool desc )
1999-11-04 22:56:02 +01:00
{
1999-11-05 00:14:30 +01:00
PGresult * res ;
2002-04-24 07:24:00 +02:00
PQExpBufferData buf ;
2000-01-14 23:18:03 +01:00
printQueryOpt myopt = pset . popt ;
1999-11-04 22:56:02 +01:00
2002-04-24 07:24:00 +02:00
initPQExpBuffer ( & buf ) ;
printfPQExpBuffer ( & buf ,
2001-06-30 19:26:12 +02:00
" SELECT d.datname as \" %s \" , \n "
" u.usename as \" %s \" " ,
_ ( " Name " ) , _ ( " Owner " ) ) ;
1999-11-04 22:56:02 +01:00
# ifdef MULTIBYTE
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf ,
2001-06-30 19:26:12 +02:00
" , \n pg_encoding_to_char(d.encoding) as \" %s \" " ,
_ ( " Encoding " ) ) ;
1999-11-04 22:56:02 +01: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 05:24:17 +01:00
if ( desc )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf ,
2001-10-25 07:50:21 +02:00
" , \n obj_description(d.oid, 'pg_database') as \" %s \" " ,
2001-06-30 19:26:12 +02:00
_ ( " Description " ) ) ;
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf ,
2001-10-25 07:50:21 +02:00
" \n FROM pg_database d LEFT JOIN pg_user u ON d.datdba = u.usesysid \n "
2001-06-30 19:26:12 +02:00
" ORDER BY 1; " ) ;
1999-11-04 22:56:02 +01:00
2002-04-24 07:24:00 +02:00
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
if ( ! res )
return false ;
1999-11-04 22:56:02 +01:00
1999-11-05 00:14:30 +01:00
myopt . nullPrint = NULL ;
2001-06-30 19:26:12 +02:00
myopt . title = _ ( " List of databases " ) ;
1999-11-04 22:56:02 +01:00
2000-01-14 23:18:03 +01:00
printQuery ( res , & myopt , pset . queryFout ) ;
1999-11-04 22:56:02 +01:00
1999-11-05 00:14:30 +01:00
PQclear ( res ) ;
return true ;
1999-11-04 22:56:02 +01:00
}
2001-06-30 19:26:12 +02:00
/*
* List Tables Grant / Revoke Permissions
1999-11-04 22:56:02 +01:00
* \ z ( now also \ dp - - perhaps more mnemonic )
*/
bool
2000-01-14 23:18:03 +01:00
permissionsList ( const char * name )
1999-11-04 22:56:02 +01:00
{
2002-04-24 07:24:00 +02:00
PQExpBufferData buf ;
1999-11-05 00:14:30 +01:00
PGresult * res ;
2000-01-14 23:18:03 +01:00
printQueryOpt myopt = pset . popt ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
initPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
/* Currently, we ignore indexes since they have no meaningful rights */
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf ,
2001-06-30 19:26:12 +02:00
" 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-05 00:14:30 +01:00
if ( name )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " AND relname ~ '^%s' \n " , name ) ;
appendPQExpBuffer ( & buf , " ORDER BY 1; " ) ;
1999-11-04 22:56:02 +01:00
2002-04-24 07:24:00 +02:00
res = PSQLexec ( buf . data ) ;
1999-11-05 00:14:30 +01:00
if ( ! res )
2002-04-24 07:24:00 +02:00
{
termPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
return false ;
2002-04-24 07:24:00 +02:00
}
1999-11-05 00:14:30 +01:00
2000-04-12 19:17:23 +02:00
myopt . nullPrint = NULL ;
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , _ ( " Access privileges for database \" %s \" " ) , PQdb ( pset . db ) ) ;
myopt . title = buf . data ;
1999-11-04 22:56:02 +01:00
2000-04-12 19:17:23 +02:00
printQuery ( res , & myopt , pset . queryFout ) ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
termPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
PQclear ( res ) ;
return true ;
1999-11-04 22:56:02 +01: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 23:18:03 +01:00
objectDescription ( const char * object )
1999-11-04 22:56:02 +01:00
{
2002-04-24 07:24:00 +02:00
PQExpBufferData buf ;
1999-11-05 00:14:30 +01:00
PGresult * res ;
2000-01-14 23:18:03 +01:00
printQueryOpt myopt = pset . popt ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
initPQExpBuffer ( & buf ) ;
printfPQExpBuffer ( & buf ,
2001-06-30 19:26:12 +02:00
" SELECT DISTINCT tt.name AS \" %s \" , tt.object AS \" %s \" , d.description AS \" %s \" \n "
" FROM ( \n "
2001-10-25 07:50:21 +02:00
/* Aggregate descriptions */
2002-04-11 22:00:18 +02: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 "
" FROM pg_proc p \n "
" WHERE p.proisagg \n "
2001-06-30 19:26:12 +02:00
2001-10-25 07:50:21 +02:00
/* Function descriptions (except in/outs for datatypes) */
2001-06-30 19:26:12 +02:00
" UNION ALL \n "
2001-08-10 20:57:42 +02:00
" SELECT p.oid as oid, p.tableoid as tableoid, \n "
2001-10-25 07:50:21 +02:00
" CAST(p.proname AS text) as name, CAST('%s' AS text) as object \n "
2001-06-30 19:26:12 +02:00
" FROM pg_proc p \n "
2002-04-11 22:00:18 +02:00
" WHERE (p.pronargs = 0 or oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg \n "
2001-06-30 19:26:12 +02:00
2002-05-13 19:45:30 +02:00
/* Operator descriptions (only if operator has its own comment) */
2001-06-30 19:26:12 +02:00
" UNION ALL \n "
2002-05-13 19:45:30 +02:00
" SELECT o.oid as oid, o.tableoid as tableoid, \n "
2001-10-25 07:50:21 +02:00
" CAST(o.oprname AS text) as name, CAST('%s' AS text) as object \n "
2001-06-30 19:26:12 +02:00
" FROM pg_operator o \n "
2001-10-25 07:50:21 +02:00
/* Type description */
2001-06-30 19:26:12 +02:00
" UNION ALL \n "
2001-08-10 20:57:42 +02:00
" SELECT t.oid as oid, t.tableoid as tableoid, \n "
2001-10-25 07:50:21 +02:00
" format_type(t.oid, NULL) as name, CAST('%s' AS text) as object \n "
2001-06-30 19:26:12 +02:00
" FROM pg_type t \n "
2001-10-25 07:50:21 +02:00
/* Relation (tables, views, indexes, sequences) descriptions */
2001-06-30 19:26:12 +02:00
" UNION ALL \n "
2001-08-10 20:57:42 +02:00
" SELECT c.oid as oid, c.tableoid as tableoid, \n "
" CAST(c.relname AS text) as name, \n "
2001-06-30 19:26:12 +02: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 "
2001-10-25 07:50:21 +02:00
/* Rule description (ignore rules for views) */
2001-06-30 19:26:12 +02:00
" UNION ALL \n "
2001-08-10 20:57:42 +02:00
" SELECT r.oid as oid, r.tableoid as tableoid, \n "
2002-04-20 01:13:54 +02:00
" CAST(r.rulename AS text) as name, CAST('%s' AS text) as object \n "
2001-06-30 19:26:12 +02:00
" FROM pg_rewrite r \n "
2002-04-20 01:13:54 +02:00
" WHERE r.rulename != '_RETURN' \n "
2001-06-30 19:26:12 +02:00
2001-10-25 07:50:21 +02:00
/* Trigger description */
2001-06-30 19:26:12 +02:00
" UNION ALL \n "
2001-08-10 20:57:42 +02:00
" SELECT t.oid as oid, t.tableoid as tableoid, \n "
2001-10-25 07:50:21 +02:00
" CAST(t.tgname AS text) as name, CAST('%s' AS text) as object \n "
2001-06-30 19:26:12 +02:00
" FROM pg_trigger t \n "
" ) AS tt, \n "
" pg_description d \n "
2001-08-10 20:57:42 +02:00
" WHERE tt.oid = d.objoid and tt.tableoid = d.classoid and d.objsubid = 0 \n " ,
2001-06-30 19:26:12 +02:00
_ ( " Name " ) , _ ( " Object " ) , _ ( " Description " ) ,
_ ( " aggregate " ) , _ ( " function " ) , _ ( " operator " ) ,
_ ( " data type " ) , _ ( " table " ) , _ ( " view " ) ,
_ ( " index " ) , _ ( " sequence " ) , _ ( " rule " ) ,
_ ( " trigger " )
) ;
1999-11-05 00:14:30 +01:00
if ( object )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " AND tt.name ~ '^%s' \n " , object ) ;
appendPQExpBuffer ( & buf , " ORDER BY 1; " ) ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
if ( ! res )
return false ;
myopt . nullPrint = NULL ;
2001-06-30 19:26:12 +02:00
myopt . title = _ ( " Object descriptions " ) ;
1999-11-05 00:14:30 +01:00
2000-01-14 23:18:03 +01:00
printQuery ( res , & myopt , pset . queryFout ) ;
1999-11-05 00:14:30 +01:00
PQclear ( res ) ;
return true ;
1999-11-04 22:56:02 +01:00
}
/*
* describeTableDetails ( for \ d )
*
2000-01-12 20:36:36 +01:00
* Unfortunately , the information presented here is so complicated that it cannot
1999-11-04 22:56:02 +01: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 20:36:36 +01:00
1999-11-05 00:14:30 +01:00
static void *
xmalloc ( size_t size )
1999-11-04 22:56:02 +01:00
{
1999-11-05 00:14:30 +01:00
void * tmp ;
tmp = malloc ( size ) ;
if ( ! tmp )
{
2000-02-08 00:10:11 +01:00
psql_error ( " out of memory \n " ) ;
1999-11-05 00:14:30 +01:00
exit ( EXIT_FAILURE ) ;
}
return tmp ;
1999-11-04 22:56:02 +01:00
}
bool
2000-01-14 23:18:03 +01:00
describeTableDetails ( const char * name , bool desc )
1999-11-04 22:56:02 +01:00
{
2002-04-24 07:24:00 +02:00
PQExpBufferData 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 05:24:17 +01:00
PGresult * res = NULL ;
2000-01-14 23:18:03 +01:00
printTableOpt myopt = pset . popt . topt ;
1999-11-05 00:14:30 +01: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 05:24:17 +01: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 01:10:14 +01:00
const char * headers [ 5 ] ;
1999-11-05 00:14:30 +01:00
char * * cells = NULL ;
char * * footers = NULL ;
char * * ptr ;
2002-04-24 07:24:00 +02:00
PQExpBufferData title ;
unsigned int cols = 0 ;
2000-04-12 19:17:23 +02:00
struct
{
bool hasindex ;
char relkind ;
int16 checks ;
int16 triggers ;
bool hasrules ;
} tableinfo ;
2002-04-24 07:24:00 +02:00
bool retval ;
2000-04-12 19:17:23 +02:00
2002-04-24 07:24:00 +02:00
retval = false ;
1999-11-05 00:14:30 +01:00
2002-04-24 07:24:00 +02:00
initPQExpBuffer ( & buf ) ;
initPQExpBuffer ( & title ) ;
1999-11-04 22:56:02 +01:00
1999-11-05 00:14:30 +01:00
/* Get general table info */
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf ,
" SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules \n "
" FROM pg_class WHERE relname='%s' " ,
name ) ;
res = PSQLexec ( buf . data ) ;
2000-04-12 19:17:23 +02:00
if ( ! res )
2002-04-24 07:24:00 +02:00
goto error_return ;
1999-11-05 00:14:30 +01:00
/* Did we get anything? */
if ( PQntuples ( res ) = = 0 )
{
2000-01-14 23:18:03 +01:00
if ( ! QUIET ( ) )
2001-06-30 19:26:12 +02:00
fprintf ( stderr , _ ( " Did not find any relation named \" %s \" . \n " ) , name ) ;
1999-11-05 00:14:30 +01:00
PQclear ( res ) ;
2002-04-24 07:24:00 +02:00
res = NULL ;
goto error_return ;
1999-11-05 00:14:30 +01:00
}
2000-04-12 19:17:23 +02: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-05 00:14:30 +01:00
2001-06-30 19:26:12 +02: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 05:24:17 +01:00
cols = 2 ;
1999-11-05 00:14:30 +01:00
2000-10-25 22:36:52 +02:00
if ( tableinfo . relkind = = ' r ' | | tableinfo . relkind = = ' v ' )
2000-04-12 19:17:23 +02:00
{
cols + + ;
2001-06-30 19:26:12 +02:00
headers [ cols - 1 ] = _ ( " Modifiers " ) ;
2000-04-12 19:17:23 +02:00
}
1999-11-05 00:14:30 +01: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 05:24:17 +01:00
if ( desc )
1999-11-05 00:14:30 +01:00
{
2000-04-12 19:17:23 +02:00
cols + + ;
2001-06-30 19:26:12 +02:00
headers [ cols - 1 ] = _ ( " Description " ) ;
1999-11-05 00:14:30 +01:00
}
2000-04-12 19:17:23 +02: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 05:24:17 +01:00
2002-03-05 03:42:56 +01:00
/* Get column info (index requires additional checks) */
if ( tableinfo . relkind = = ' i ' )
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , " SELECT \n CASE i.indproc WHEN ('-'::regproc) THEN a.attname \n ELSE SUBSTR(pg_get_indexdef(attrelid), \n POSITION('(' in pg_get_indexdef(attrelid))) \n END, " ) ;
2002-03-05 03:42:56 +01:00
else
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , " SELECT a.attname, " ) ;
appendPQExpBuffer ( & buf , " 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 05:24:17 +01:00
if ( desc )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " , col_description(a.attrelid, a.attnum) " ) ;
appendPQExpBuffer ( & buf , " \n FROM pg_class c, pg_attribute a " ) ;
2002-03-05 03:42:56 +01:00
if ( tableinfo . relkind = = ' i ' )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " , pg_index i " ) ;
appendPQExpBuffer ( & buf , " \n WHERE c.relname = '%s' \n AND a.attnum > 0 AND a.attrelid = c.oid " , name ) ;
2002-03-05 03:42:56 +01:00
if ( tableinfo . relkind = = ' i ' )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " AND a.attrelid = i.indexrelid " ) ;
appendPQExpBuffer ( & buf , " \n ORDER BY 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 05:24:17 +01:00
2002-04-24 07:24:00 +02:00
res = PSQLexec ( buf . data ) ;
* 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 05:24:17 +01:00
if ( ! res )
2002-04-24 07:24:00 +02:00
goto error_return ;
* 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 05:24:17 +01:00
/* Check if table is a view */
2000-04-12 19:17:23 +02:00
if ( tableinfo . hasrules )
{
PGresult * result ;
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , " SELECT definition FROM pg_views WHERE viewname = '%s' " , name ) ;
result = PSQLexec ( buf . data ) ;
2000-04-12 19:17:23 +02:00
if ( ! result )
{
PQclear ( res ) ;
PQclear ( result ) ;
2002-04-24 07:24:00 +02:00
goto error_return ;
2000-04-12 19:17:23 +02:00
}
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 05:24:17 +01:00
/* Generate table cells to be printed */
cells = xmalloc ( ( PQntuples ( res ) * cols + 1 ) * sizeof ( * cells ) ) ;
2000-04-12 19:17:23 +02: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 05:24:17 +01:00
1999-11-05 00:14:30 +01:00
for ( i = 0 ; i < PQntuples ( res ) ; i + + )
{
/* Name */
2000-04-12 19:17:23 +02:00
cells [ i * cols + 0 ] = PQgetvalue ( res , i , 0 ) ; /* don't free this
* afterwards */
1999-11-05 00:14:30 +01:00
/* Type */
2000-07-07 21:24:43 +02:00
cells [ i * cols + 1 ] = PQgetvalue ( res , i , 1 ) ; /* don't free this
2001-03-22 05:01:46 +01: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 05:24:17 +01:00
/* Extra: not null and default */
/* (I'm cutting off the 'default' string at 128) */
2000-10-25 22:36:52 +02:00
if ( tableinfo . relkind = = ' r ' | | tableinfo . relkind = = ' v ' )
2000-04-12 19:17:23 +02:00
{
cells [ i * cols + 2 ] = xmalloc ( 128 + 128 ) ;
cells [ i * cols + 2 ] [ 0 ] = ' \0 ' ;
2000-07-07 21:24:43 +02:00
if ( strcmp ( PQgetvalue ( res , i , 2 ) , " t " ) = = 0 )
2000-04-12 19:17:23 +02:00
strcat ( cells [ i * cols + 2 ] , " not null " ) ;
/* handle "default" here */
2000-07-07 21:24:43 +02:00
if ( strcmp ( PQgetvalue ( res , i , 3 ) , " t " ) = = 0 )
2000-04-12 19:17:23 +02:00
{
PGresult * result ;
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & 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 " ,
name , PQgetvalue ( res , i , 4 ) ) ;
result = PSQLexec ( buf . data ) ;
if ( cells [ i * cols + 2 ] [ 0 ] )
strcat ( cells [ i * cols + 2 ] , " " ) ;
strcat ( cells [ i * cols + 2 ] , " default " ) ;
strcat ( cells [ i * cols + 2 ] , result ? PQgetvalue ( result , 0 , 0 ) : " ? " ) ;
PQclear ( result ) ;
2000-04-12 19:17:23 +02:00
}
}
1999-11-05 00:14:30 +01: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 05:24:17 +01:00
if ( desc )
2000-07-07 21:24:43 +02:00
cells [ i * cols + cols - 1 ] = PQgetvalue ( res , i , 5 ) ;
1999-11-05 00:14:30 +01:00
}
1999-11-04 22:56:02 +01:00
1999-11-05 00:14:30 +01:00
/* Make title */
2000-04-12 19:17:23 +02:00
switch ( tableinfo . relkind )
{
case ' r ' :
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & title , _ ( " Table \" %s \" " ) , name ) ;
2000-10-25 22:36:52 +02:00
break ;
case ' v ' :
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & title , _ ( " View \" %s \" " ) , name ) ;
2000-04-12 19:17:23 +02:00
break ;
case ' S ' :
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & title , _ ( " Sequence \" %s \" " ) , name ) ;
2000-04-12 19:17:23 +02:00
break ;
case ' i ' :
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & title , _ ( " Index \" %s \" " ) , name ) ;
2000-04-12 19:17:23 +02:00
break ;
case ' s ' :
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & title , _ ( " Special relation \" %s \" " ) , name ) ;
2000-04-12 19:17:23 +02:00
break ;
2001-08-09 05:32:16 +02:00
case ' t ' :
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & title , _ ( " TOAST table \" %s \" " ) , name ) ;
2001-08-09 05:32:16 +02:00
break ;
2000-04-12 19:17:23 +02:00
default :
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & title , _ ( " ?%c? \" %s \" " ) , tableinfo . relkind , name ) ;
2000-10-25 22:36:52 +02:00
break ;
2000-04-12 19:17:23 +02:00
}
1999-11-05 00:14:30 +01:00
/* Make footers */
2000-04-12 19:17:23 +02:00
if ( tableinfo . relkind = = ' i ' )
{
2001-08-06 00:13:46 +02:00
/* Footer information about an index */
2000-04-12 19:17:23 +02:00
PGresult * result ;
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf ,
" SELECT i.indisunique, i.indisprimary, a.amname, c2.relname, \n "
" pg_get_expr(i.indpred,i.indrelid) \n "
" FROM pg_index i, pg_class c, pg_class c2, pg_am a \n "
" WHERE i.indexrelid = c.oid AND c.relname = '%s' AND c.relam = a.oid \n "
" AND i.indrelid = c2.oid " ,
name ) ;
result = PSQLexec ( buf . data ) ;
if ( ! result )
goto error_return ;
else if ( PQntuples ( result ) ! = 1 )
{
PQclear ( result ) ;
goto error_return ;
}
2000-04-12 19:17:23 +02:00
else
{
2002-04-24 08:17:04 +02:00
PQExpBufferData tmpbuf ;
2001-10-25 07:50:21 +02:00
char * indisunique = PQgetvalue ( result , 0 , 0 ) ;
char * indisprimary = PQgetvalue ( result , 0 , 1 ) ;
char * indamname = PQgetvalue ( result , 0 , 2 ) ;
2002-03-05 03:42:56 +01:00
char * indtable = PQgetvalue ( result , 0 , 3 ) ;
char * indpred = PQgetvalue ( result , 0 , 4 ) ;
2001-08-06 00:13:46 +02:00
2002-04-24 08:17:04 +02:00
initPQExpBuffer ( & tmpbuf ) ;
if ( strcmp ( indisprimary , " t " ) = = 0 )
printfPQExpBuffer ( & tmpbuf , _ ( " primary key, " ) ) ;
else if ( strcmp ( indisunique , " t " ) = = 0 )
printfPQExpBuffer ( & tmpbuf , _ ( " unique, " ) ) ;
else
resetPQExpBuffer ( & tmpbuf ) ;
appendPQExpBuffer ( & tmpbuf , " %s, " , indamname ) ;
appendPQExpBuffer ( & tmpbuf , _ ( " for table \" %s \" " ) , indtable ) ;
if ( strlen ( indpred ) )
appendPQExpBuffer ( & tmpbuf , " , predicate %s " , indpred ) ;
2002-03-05 03:42:56 +01:00
footers = xmalloc ( 2 * sizeof ( * footers ) ) ;
2002-04-24 08:17:04 +02:00
footers [ 0 ] = xstrdup ( tmpbuf . data ) ;
2002-03-05 03:42:56 +01:00
footers [ 1 ] = NULL ;
2002-04-24 08:17:04 +02:00
termPQExpBuffer ( & tmpbuf ) ;
2000-04-12 19:17:23 +02:00
}
2001-08-21 18:36:06 +02:00
PQclear ( result ) ;
2000-04-12 19:17:23 +02:00
}
2000-10-25 22:36:52 +02:00
else if ( view_def )
1999-11-05 00:14:30 +01:00
{
2002-04-05 13:52:38 +02:00
PGresult * result = NULL ;
int rule_count = 0 ;
int count_footers = 0 ;
/* count rules */
2002-04-24 07:24:00 +02:00
if ( tableinfo . hasrules )
2002-04-05 13:52:38 +02:00
{
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf ,
2002-04-05 13:52:38 +02:00
" SELECT r.rulename \n "
" FROM pg_rewrite r, pg_class c \n "
2002-04-20 01:13:54 +02:00
" WHERE c.relname = '%s' AND c.oid = r.ev_class \n "
" AND r.rulename != '_RETURN' " ,
2002-04-05 13:52:38 +02:00
name ) ;
2002-04-24 07:24:00 +02:00
result = PSQLexec ( buf . data ) ;
2002-04-05 13:52:38 +02:00
if ( ! result )
2002-04-24 07:24:00 +02:00
goto error_return ;
2002-04-05 13:52:38 +02:00
else
rule_count = PQntuples ( result ) ;
}
2001-08-06 00:13:46 +02:00
/* Footer information about a view */
2002-04-05 13:52:38 +02:00
footers = xmalloc ( ( rule_count + 2 ) * sizeof ( * footers ) ) ;
footers [ count_footers ] = xmalloc ( 64 + strlen ( view_def ) ) ;
snprintf ( footers [ count_footers ] , 64 + strlen ( view_def ) ,
2001-06-30 19:26:12 +02:00
_ ( " View definition: %s " ) , view_def ) ;
2002-04-05 13:52:38 +02:00
count_footers + + ;
/* print rules */
for ( i = 0 ; i < rule_count ; i + + )
{
char * s = _ ( " Rules " ) ;
if ( i = = 0 )
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , " %s: %s " , s , PQgetvalue ( result , i , 0 ) ) ;
2002-04-05 13:52:38 +02:00
else
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , " %*s %s " , ( int ) strlen ( s ) , " " , PQgetvalue ( result , i , 0 ) ) ;
2002-04-05 13:52:38 +02:00
if ( i < rule_count - 1 )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " , " ) ;
2002-04-05 13:52:38 +02:00
2002-04-24 07:24:00 +02:00
footers [ count_footers + + ] = xstrdup ( buf . data ) ;
2002-04-05 13:52:38 +02:00
}
PQclear ( result ) ;
footers [ count_footers ] = NULL ;
1999-11-05 00:14:30 +01: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 05:24:17 +01:00
else if ( tableinfo . relkind = = ' r ' )
1999-11-05 00:14:30 +01:00
{
2001-08-06 00:13:46 +02:00
/* Footer information about a table */
2001-10-25 07:50:21 +02:00
PGresult * result1 = NULL ,
* result2 = NULL ,
* result3 = NULL ,
2002-03-05 03:42:56 +01:00
* result4 = NULL ;
2000-04-12 19:17:23 +02:00
int index_count = 0 ,
2001-10-25 07:50:21 +02:00
constr_count = 0 ,
rule_count = 0 ,
trigger_count = 0 ;
2000-04-12 19:17:23 +02: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 05:24:17 +01:00
2001-06-30 19:26:12 +02:00
/* count indexes */
2002-04-24 07:24:00 +02:00
if ( tableinfo . hasindex )
2000-04-12 19:17:23 +02:00
{
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf ,
" SELECT c2.relname, i.indisprimary, i.indisunique, \n "
2002-03-05 03:42:56 +01:00
" SUBSTR(pg_get_indexdef(i.indexrelid), \n "
" POSITION('USING ' IN pg_get_indexdef(i.indexrelid))+5) \n "
2000-04-12 19:17:23 +02:00
" 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 "
2002-03-05 03:42:56 +01:00
" ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname " ,
2000-04-12 19:17:23 +02:00
name ) ;
2002-04-24 07:24:00 +02:00
result1 = PSQLexec ( buf . data ) ;
2000-04-12 19:17:23 +02:00
if ( ! result1 )
2002-04-24 07:24:00 +02:00
goto error_return ;
2000-04-12 19:17:23 +02:00
else
index_count = PQntuples ( result1 ) ;
}
/* count table (and column) constraints */
2002-04-24 07:24:00 +02:00
if ( tableinfo . checks )
2000-04-12 19:17:23 +02:00
{
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf ,
" SELECT rcsrc, rcname \n "
2000-04-12 19:17:23 +02:00
" FROM pg_relcheck r, pg_class c \n "
" WHERE c.relname='%s' AND c.oid = r.rcrelid " ,
name ) ;
2002-04-24 07:24:00 +02:00
result2 = PSQLexec ( buf . data ) ;
2000-04-12 19:17:23 +02:00
if ( ! result2 )
2002-04-24 07:24:00 +02:00
goto error_return ;
2000-04-12 19:17:23 +02:00
else
constr_count = PQntuples ( result2 ) ;
}
/* count rules */
2002-04-24 07:24:00 +02:00
if ( tableinfo . hasrules )
2000-04-12 19:17:23 +02:00
{
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf ,
2000-04-12 19:17:23 +02:00
" SELECT r.rulename \n "
" FROM pg_rewrite r, pg_class c \n "
" WHERE c.relname='%s' AND c.oid = r.ev_class " ,
name ) ;
2002-04-24 07:24:00 +02:00
result3 = PSQLexec ( buf . data ) ;
2000-04-12 19:17:23 +02:00
if ( ! result3 )
2002-04-24 07:24:00 +02:00
goto error_return ;
2000-04-12 19:17:23 +02:00
else
rule_count = PQntuples ( result3 ) ;
}
/* count triggers */
2002-04-24 07:24:00 +02:00
if ( tableinfo . triggers )
2000-04-12 19:17:23 +02:00
{
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf ,
2000-04-12 19:17:23 +02:00
" SELECT t.tgname \n "
" FROM pg_trigger t, pg_class c \n "
" WHERE c.relname='%s' AND c.oid = t.tgrelid " ,
name ) ;
2002-04-24 07:24:00 +02:00
result4 = PSQLexec ( buf . data ) ;
2000-04-12 19:17:23 +02:00
if ( ! result4 )
2002-04-24 07:24:00 +02:00
goto error_return ;
2000-04-12 19:17:23 +02:00
else
trigger_count = PQntuples ( result4 ) ;
}
2002-03-05 03:42:56 +01:00
footers = xmalloc ( ( index_count + constr_count + rule_count + trigger_count + 1 )
2001-10-25 07:50:21 +02:00
* sizeof ( * footers ) ) ;
2000-04-12 19:17:23 +02:00
2001-06-30 19:26:12 +02:00
/* print indexes */
2000-04-12 19:17:23 +02:00
for ( i = 0 ; i < index_count ; i + + )
{
2001-10-25 07:50:21 +02:00
char * s = _ ( " Indexes " ) ;
2002-03-05 03:42:56 +01:00
2001-06-30 19:26:12 +02:00
if ( i = = 0 )
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , " %s: %s " , s , PQgetvalue ( result1 , i , 0 ) ) ;
2001-06-30 19:26:12 +02:00
else
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , " %*s %s " , ( int ) strlen ( s ) , " " , PQgetvalue ( result1 , i , 0 ) ) ;
2000-04-12 19:17:23 +02:00
2002-03-05 03:42:56 +01:00
/* Label as primary key or unique (but not both) */
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf ,
strcmp ( PQgetvalue ( result1 , i , 1 ) , " t " ) = = 0
? _ ( " primary key " ) :
( strcmp ( PQgetvalue ( result1 , i , 2 ) , " t " ) = = 0
? _ ( " unique " )
: " " ) ) ;
2000-04-12 19:17:23 +02:00
2002-03-05 03:42:56 +01:00
/* Everything after "USING" is echoed verbatim */
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " %s " , PQgetvalue ( result1 , i , 3 ) ) ;
2001-06-30 19:26:12 +02:00
2002-03-05 03:42:56 +01:00
if ( i < index_count - 1 )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " , " ) ;
2001-05-28 04:01:22 +02:00
2002-04-24 07:24:00 +02:00
footers [ count_footers + + ] = xstrdup ( buf . data ) ;
2001-05-28 04:01:22 +02:00
}
/* print constraints */
for ( i = 0 ; i < constr_count ; i + + )
{
2001-10-25 07:50:21 +02:00
char * s = _ ( " Check constraints " ) ;
2001-06-30 19:26:12 +02:00
if ( i = = 0 )
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , _ ( " %s: \" %s \" %s " ) ,
s ,
PQgetvalue ( result2 , i , 1 ) ,
PQgetvalue ( result2 , i , 0 ) ) ;
2001-06-30 19:26:12 +02:00
else
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , _ ( " %*s \" %s \" %s " ) ,
( int ) strlen ( s ) , " " ,
PQgetvalue ( result2 , i , 1 ) ,
PQgetvalue ( result2 , i , 0 ) ) ;
footers [ count_footers + + ] = xstrdup ( buf . data ) ;
2000-04-12 19:17:23 +02:00
}
/* print rules */
for ( i = 0 ; i < rule_count ; i + + )
{
2001-10-25 07:50:21 +02:00
char * s = _ ( " Rules " ) ;
2001-06-30 19:26:12 +02:00
if ( i = = 0 )
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , " %s: %s " , s , PQgetvalue ( result3 , i , 0 ) ) ;
2001-06-30 19:26:12 +02:00
else
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , " %*s %s " , ( int ) strlen ( s ) , " " , PQgetvalue ( result3 , i , 0 ) ) ;
2000-04-12 19:17:23 +02:00
if ( i < rule_count - 1 )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " , " ) ;
2000-04-12 19:17:23 +02:00
2002-04-24 07:24:00 +02:00
footers [ count_footers + + ] = xstrdup ( buf . data ) ;
2000-04-12 19:17:23 +02:00
}
/* print triggers */
for ( i = 0 ; i < trigger_count ; i + + )
{
2001-10-25 07:50:21 +02:00
char * s = _ ( " Triggers " ) ;
2001-06-30 19:26:12 +02:00
if ( i = = 0 )
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , " %s: %s " , s , PQgetvalue ( result4 , i , 0 ) ) ;
2001-06-30 19:26:12 +02:00
else
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf , " %*s %s " , ( int ) strlen ( s ) , " " , PQgetvalue ( result4 , i , 0 ) ) ;
2000-04-12 19:17:23 +02:00
if ( i < trigger_count - 1 )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " , " ) ;
2000-04-12 19:17:23 +02:00
2002-04-24 07:24:00 +02:00
footers [ count_footers + + ] = xstrdup ( buf . data ) ;
2000-04-12 19:17:23 +02:00
}
/* end of list marker */
footers [ count_footers ] = NULL ;
PQclear ( result1 ) ;
PQclear ( result2 ) ;
PQclear ( result3 ) ;
PQclear ( result4 ) ;
* 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 05:24:17 +01:00
}
1999-11-04 22:56:02 +01:00
2002-04-24 07:24:00 +02:00
printTable ( title . data , headers ,
( const char * * ) cells , ( const char * * ) footers ,
" llll " , & myopt , pset . queryFout ) ;
retval = true ;
error_return :
1999-11-04 22:56:02 +01:00
1999-11-05 00:14:30 +01:00
/* clean up */
2002-04-24 07:24:00 +02:00
termPQExpBuffer ( & buf ) ;
termPQExpBuffer ( & title ) ;
1999-11-04 22:56:02 +01:00
2002-04-24 07:24:00 +02:00
if ( cells )
1999-11-05 00:14:30 +01:00
{
2002-04-24 07:24:00 +02:00
for ( i = 0 ; i < PQntuples ( res ) ; i + + )
if ( tableinfo . relkind = = ' r ' | | tableinfo . relkind = = ' v ' )
free ( cells [ i * cols + 2 ] ) ;
free ( cells ) ;
1999-11-05 00:14:30 +01:00
}
1999-11-04 22:56:02 +01:00
2002-04-24 07:24:00 +02:00
if ( footers )
{
for ( ptr = footers ; * ptr ; ptr + + )
free ( * ptr ) ;
free ( footers ) ;
}
1999-11-04 22:56:02 +01:00
2002-04-24 07:24:00 +02:00
if ( res )
PQclear ( res ) ;
1999-11-04 22:56:02 +01:00
2002-04-24 07:24:00 +02:00
return retval ;
1999-11-04 22:56:02 +01:00
}
2001-05-09 19:29:10 +02:00
/*
* \ du [ user ]
*
* Describes users , possibly based on a simplistic prefix search on the
* argument .
*/
bool
2001-10-25 07:50:21 +02:00
describeUsers ( const char * name )
2001-05-09 19:29:10 +02:00
{
2002-04-24 07:24:00 +02:00
PQExpBufferData buf ;
2001-05-09 19:29:10 +02:00
PGresult * res ;
2001-06-30 19:26:12 +02:00
printQueryOpt myopt = pset . popt ;
2001-10-25 07:50:21 +02:00
2002-04-24 07:24:00 +02:00
initPQExpBuffer ( & buf ) ;
printfPQExpBuffer ( & buf ,
2001-06-30 19:26:12 +02:00
" SELECT u.usename AS \" %s \" , \n "
" u.usesysid AS \" %s \" , \n "
2002-04-24 07:24:00 +02:00
" CASE WHEN u.usesuper AND u.usecreatedb THEN CAST('%s' AS text) \n "
2001-06-30 19:26:12 +02:00
" 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 " ) ,
2001-10-25 07:50:21 +02:00
_ ( " Attributes " ) ) ;
2001-05-09 19:29:10 +02:00
if ( name )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " WHERE u.usename ~ '^%s' \n " , name ) ;
appendPQExpBuffer ( & buf , " ORDER BY 1; " ) ;
2001-05-09 19:29:10 +02:00
2002-04-24 07:24:00 +02:00
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
2001-05-09 19:29:10 +02:00
if ( ! res )
return false ;
2001-06-30 19:26:12 +02:00
myopt . nullPrint = NULL ;
myopt . title = _ ( " List of database users " ) ;
2001-05-09 19:29:10 +02:00
2001-06-30 19:26:12 +02:00
printQuery ( res , & myopt , pset . queryFout ) ;
2001-05-09 19:29:10 +02:00
PQclear ( res ) ;
return true ;
}
1999-11-04 22:56:02 +01:00
/*
* listTables ( )
*
* handler for \ d , \ dt , etc .
*
* The infotype is an array of characters , specifying what info is desired :
* t - tables
2001-06-30 19:26:12 +02:00
* i - indexes
1999-11-04 22:56:02 +01: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 05:24:17 +01:00
* S - systems tables ( ~ ' ^ pg_ ' )
1999-11-04 22:56:02 +01:00
* ( any order of the above is fine )
2000-01-12 20:36:36 +01: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 22:56:02 +01:00
*/
bool
2000-01-14 23:18:03 +01:00
listTables ( const char * infotype , const char * name , bool desc )
1999-11-04 22:56:02 +01:00
{
1999-11-05 00:14:30 +01:00
bool showTables = strchr ( infotype , ' t ' ) ! = NULL ;
2001-06-30 19:26:12 +02:00
bool showIndexes = strchr ( infotype , ' i ' ) ! = NULL ;
1999-11-05 00:14:30 +01:00
bool showViews = strchr ( infotype , ' v ' ) ! = NULL ;
bool showSeq = strchr ( infotype , ' s ' ) ! = NULL ;
bool showSystem = strchr ( infotype , ' S ' ) ! = NULL ;
2002-04-24 07:24:00 +02:00
PQExpBufferData buf ;
1999-11-05 00:14:30 +01:00
PGresult * res ;
2000-01-14 23:18:03 +01:00
printQueryOpt myopt = pset . popt ;
1999-11-05 00:14:30 +01:00
2001-06-30 19:26:12 +02:00
if ( showSystem & & ! ( showSeq | | showIndexes | | showViews | | showTables ) )
2000-04-16 22:04:51 +02:00
showTables = showViews = showSeq = true ;
2002-04-24 07:24:00 +02:00
initPQExpBuffer ( & buf ) ;
2000-04-16 22:04:51 +02:00
2002-04-24 07:24:00 +02:00
printfPQExpBuffer ( & buf ,
2001-06-30 19:26:12 +02:00
" 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 20:36:36 +01:00
2001-06-30 19:26:12 +02:00
if ( desc )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf ,
2001-08-10 20:57:42 +02:00
" , \n obj_description(c.oid, 'pg_class') as \" %s \" " ,
2001-06-30 19:26:12 +02:00
_ ( " Description " ) ) ;
2002-04-24 07:24:00 +02:00
if ( showIndexes )
appendPQExpBuffer ( & buf ,
" , \n c2.relname as \" %s \" "
" \n FROM pg_class c, pg_class c2, pg_index i, pg_user u \n "
" WHERE c.relowner = u.usesysid \n "
" AND i.indrelid = c2.oid AND i.indexrelid = c.oid \n " ,
_ ( " Table " ) ) ;
else
appendPQExpBuffer ( & buf ,
" \n FROM pg_class c, pg_user u \n "
" WHERE c.relowner = u.usesysid \n " ) ;
appendPQExpBuffer ( & buf , " AND c.relkind IN ( " ) ;
2001-06-30 19:26:12 +02:00
if ( showTables )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " 'r', " ) ;
1999-11-05 00:14:30 +01:00
if ( showViews )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " 'v', " ) ;
2001-06-30 19:26:12 +02:00
if ( showIndexes )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " 'i', " ) ;
2001-06-30 19:26:12 +02:00
if ( showSeq )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " 'S', " ) ;
1999-11-05 00:14:30 +01:00
if ( showSystem & & showTables )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " 's', " ) ;
appendPQExpBuffer ( & buf , " '' " ) ; /* dummy */
appendPQExpBuffer ( & buf , " ) \n " ) ;
1999-11-05 00:14:30 +01:00
2001-06-30 19:26:12 +02:00
if ( showSystem )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " AND c.relname ~ '^pg_' \n " ) ;
2001-06-30 19:26:12 +02:00
else
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " AND c.relname !~ '^pg_' \n " ) ;
2000-01-12 20:36:36 +01:00
2001-06-30 19:26:12 +02:00
if ( name )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " AND c.relname ~ '^%s' \n " , name ) ;
1999-11-04 22:56:02 +01:00
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " ORDER BY 1; " ) ;
1999-11-04 22:56:02 +01:00
2002-04-24 07:24:00 +02:00
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
1999-11-05 00:14:30 +01:00
if ( ! res )
return false ;
1999-11-04 22:56:02 +01:00
2000-01-14 23:18:03 +01:00
if ( PQntuples ( res ) = = 0 & & ! QUIET ( ) )
2000-04-12 19:17:23 +02:00
{
if ( name )
2001-06-30 19:26:12 +02:00
fprintf ( pset . queryFout , _ ( " No matching relations found. \n " ) ) ;
2000-04-12 19:17:23 +02:00
else
2001-06-30 19:26:12 +02:00
fprintf ( pset . queryFout , _ ( " No relations found. \n " ) ) ;
2000-04-12 19:17:23 +02:00
}
1999-11-05 00:14:30 +01:00
else
{
myopt . nullPrint = NULL ;
2001-06-30 19:26:12 +02:00
myopt . title = _ ( " List of relations " ) ;
1999-11-04 22:56:02 +01:00
2000-01-14 23:18:03 +01:00
printQuery ( res , & myopt , pset . queryFout ) ;
1999-11-05 00:14:30 +01:00
}
1999-11-04 22:56:02 +01:00
1999-11-05 00:14:30 +01:00
PQclear ( res ) ;
return true ;
1999-11-04 22:56:02 +01:00
}
2002-03-19 03:32:21 +01:00
2002-04-24 07:24:00 +02:00
2002-03-19 03:32:21 +01:00
/*
* \ dD [ domain ]
*
* Describes domains , possibly based on a simplistic prefix search on the
* argument .
*/
bool
listDomains ( const char * name )
{
2002-04-24 07:24:00 +02:00
PQExpBufferData buf ;
2002-03-19 03:32:21 +01:00
PGresult * res ;
printQueryOpt myopt = pset . popt ;
2002-04-24 07:24:00 +02:00
initPQExpBuffer ( & buf ) ;
printfPQExpBuffer ( & buf ,
2002-03-19 03:32:21 +01:00
" SELECT t.typname as \" %s \" , \n "
2002-04-24 07:24:00 +02:00
" format_type(t.typbasetype, t.typtypmod) as \" %s \" , \n "
2002-03-19 03:32:21 +01:00
" CASE WHEN t.typnotnull AND t.typdefault IS NOT NULL THEN 'not null default '||t.typdefault \n "
" WHEN t.typnotnull AND t.typdefault IS NULL THEN 'not null' \n "
" WHEN NOT t.typnotnull AND t.typdefault IS NOT NULL THEN 'default '||t.typdefault \n "
" ELSE '' \n "
" END as \" %s \" \n "
" FROM pg_type t \n "
" WHERE t.typtype = 'd' \n " ,
_ ( " Name " ) ,
_ ( " Type " ) ,
_ ( " Modifier " ) ) ;
if ( name )
2002-04-24 07:24:00 +02:00
appendPQExpBuffer ( & buf , " AND t.typname ~ '^%s' \n " , name ) ;
appendPQExpBuffer ( & buf , " ORDER BY 1; " ) ;
2002-03-19 03:32:21 +01:00
2002-04-24 07:24:00 +02:00
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
2002-03-19 03:32:21 +01:00
if ( ! res )
return false ;
myopt . nullPrint = NULL ;
2002-04-24 07:24:00 +02:00
myopt . title = _ ( " List of domains " ) ;
2002-03-19 03:32:21 +01:00
printQuery ( res , & myopt , pset . queryFout ) ;
PQclear ( res ) ;
return true ;
}