1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-08 11:42:09 +03:00

Add pg_description table for info on tables, columns, operators, types, and aggregates. Modify psql with new \dd operator to access description

This commit is contained in:
Bruce Momjian
1997-11-13 03:23:18 +00:00
parent 7e48d427c8
commit 5071ae2972
16 changed files with 1890 additions and 51 deletions

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.101 1997/11/07 06:27:52 thomas Exp $
* $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.102 1997/11/13 03:22:42 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -116,6 +116,7 @@ handleCopyIn(PGresult *res, const bool mustprompt,
FILE *copystream);
static int tableList(PsqlSettings *pset, bool deep_tablelist, char info_type);
static int tableDesc(PsqlSettings *pset, char *table, FILE *fout);
static int objectDescription(PsqlSettings *pset, char *object, FILE *fout);
static int rightsList(PsqlSettings *pset);
static void prompt_for_password(char *username, char *password);
static char *
@ -224,6 +225,7 @@ slashUsage(PsqlSettings *pset)
fprintf(fout, " \\connect <dbname|-> <user> -- connect to new database (currently '%s')\n", PQdb(pset->db));
fprintf(fout, " \\copy table {from | to} <fname>\n");
fprintf(fout, " \\d [<table>] -- list tables and indices in database or columns in <table>, * for all\n");
fprintf(fout, " \\dc [<object>]- list comment for table, field, type, function, or operator.\n");
fprintf(fout, " \\di -- list only indices in database\n");
fprintf(fout, " \\ds -- list only sequences in database\n");
fprintf(fout, " \\dt -- list only tables in database\n");
@ -331,8 +333,8 @@ tableList(PsqlSettings *pset, bool deep_tablelist, char info_type)
#endif
listbuf[0] = '\0';
strcat(listbuf, "SELECT usename, relname, relkind, relhasrules");
strcat(listbuf, " FROM pg_class, pg_user ");
strcat(listbuf, "SELECT usename, relname, relkind, relhasrules ");
strcat(listbuf, "FROM pg_class, pg_user ");
switch (info_type)
{
case 't':
@ -356,8 +358,8 @@ tableList(PsqlSettings *pset, bool deep_tablelist, char info_type)
* the usesysid = relowner won't work on stock 1.0 dbs, need to add in
* the int4oideq function
*/
strcat(listbuf, " and usesysid = relowner");
strcat(listbuf, " ORDER BY relname ");
strcat(listbuf, " and usesysid = relowner");
strcat(listbuf, " ORDER BY relname ");
if (!(res = PSQLexec(pset, listbuf)))
return -1;
/* first, print out the attribute names */
@ -472,8 +474,8 @@ rightsList(PsqlSettings *pset)
PGresult *res;
listbuf[0] = '\0';
strcat(listbuf, "SELECT relname, relacl");
strcat(listbuf, " FROM pg_class, pg_user ");
strcat(listbuf, "SELECT relname, relacl ");
strcat(listbuf, "FROM pg_class, pg_user ");
strcat(listbuf, "WHERE ( relkind = 'r' OR relkind = 'i') ");
strcat(listbuf, " and relname !~ '^pg_'");
strcat(listbuf, " and relname !~ '^xin[vx][0-9]+'");
@ -560,9 +562,9 @@ tableDesc(PsqlSettings *pset, char *table, FILE *fout)
}
descbuf[0] = '\0';
strcat(descbuf, "SELECT a.attnum, a.attname, t.typname, a.attlen, a.attnotnull");
strcat(descbuf, " FROM pg_class c, pg_attribute a, pg_type t ");
strcat(descbuf, " WHERE c.relname = '");
strcat(descbuf, "SELECT a.attnum, a.attname, t.typname, a.attlen, a.attnotnull ");
strcat(descbuf, "FROM pg_class c, pg_attribute a, pg_type t ");
strcat(descbuf, "WHERE c.relname = '");
strcat(descbuf, table);
strcat(descbuf, "'");
strcat(descbuf, " and a.attnum > 0 ");
@ -659,6 +661,197 @@ tableDesc(PsqlSettings *pset, char *table, FILE *fout)
}
}
/*
* Get object comments
*
* Describe the columns in a database table. returns 0 if all went well
*
*
*/
int
objectDescription(PsqlSettings *pset, char *object, FILE *fout)
{
char descbuf[256];
int nDescriptions;
int i;
PGresult *res;
int usePipe = 0;
char *pagerenv;
#ifdef TIOCGWINSZ
if (fout == NULL &&
pset->notty == 0 &&
(ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
screen_size.ws_col == 0 ||
screen_size.ws_row == 0))
{
#endif
screen_size.ws_row = 24;
screen_size.ws_col = 80;
#ifdef TIOCGWINSZ
}
#endif
/* Build the query */
while (isspace(*object))
object++;
/* if the object name is surrounded by double-quotes, then don't convert case */
if (*object == '"')
{
object++;
if (*(object+strlen(object)-1) == '"')
*(object+strlen(object)-1) = '\0';
}
else
{
for (i = strlen(object); i >= 0; i--)
if (isupper(object[i]))
object[i] = tolower(object[i]);
}
descbuf[0] = '\0';
if (strchr(object,'.') != NULL)
{
char table[NAMEDATALEN],column[NAMEDATALEN];
StrNCpy(table,object,
((strchr(object,'.')-object+1) < NAMEDATALEN) ?
(strchr(object,'.')-object+1) : NAMEDATALEN);
StrNCpy(column,strchr(object,'.')+1,NAMEDATALEN);
strcat(descbuf, "SELECT DISTINCT description ");
strcat(descbuf, "FROM pg_class, pg_attribute, pg_description ");
strcat(descbuf, "WHERE pg_class.relname = '");
strcat(descbuf, table);
strcat(descbuf, "' and ");
strcat(descbuf, "pg_class.oid = pg_attribute.attrelid and ");
strcat(descbuf, "pg_attribute.attname = '");
strcat(descbuf, column);
strcat(descbuf, "' and ");
strcat(descbuf, " pg_attribute.oid = pg_description.rowoid " );
if (!(res = PSQLexec(pset, descbuf)))
return -1;
}
else
{
strcat(descbuf, "SELECT DISTINCT description ");
strcat(descbuf, "FROM pg_class, pg_description ");
strcat(descbuf, "WHERE pg_class.relname = '");
strcat(descbuf, object);
strcat(descbuf, "'" );
strcat(descbuf, " and pg_class.oid = pg_description.rowoid " );
if (!(res = PSQLexec(pset, descbuf)))
return -1;
else if (PQntuples(res) <= 0)
{
PQclear(res);
descbuf[0] = '\0';
strcat(descbuf, "SELECT DISTINCT description ");
strcat(descbuf, "FROM pg_type, pg_description ");
strcat(descbuf, "WHERE pg_type.typname = '");
strcat(descbuf, object);
strcat(descbuf, "'" );
strcat(descbuf, " and pg_type.oid = pg_description.rowoid " );
if (!(res = PSQLexec(pset, descbuf)))
return -1;
else if (PQntuples(res) <= 0)
{
PQclear(res);
descbuf[0] = '\0';
strcat(descbuf, "SELECT DISTINCT description ");
strcat(descbuf, "FROM pg_type, pg_description ");
strcat(descbuf, "WHERE pg_type.typname = '");
strcat(descbuf, object);
strcat(descbuf, "'" );
strcat(descbuf, " and pg_type.oid = pg_description.rowoid " );
if (!(res = PSQLexec(pset, descbuf)))
return -1;
else if (PQntuples(res) <= 0)
{
PQclear(res);
descbuf[0] = '\0';
strcat(descbuf, "SELECT DISTINCT description ");
strcat(descbuf, "FROM pg_proc, pg_description ");
strcat(descbuf, "WHERE pg_proc.proname = '");
strcat(descbuf, object);
strcat(descbuf, "'" );
strcat(descbuf, " and pg_proc.oid = pg_description.rowoid " );
if (!(res = PSQLexec(pset, descbuf)))
return -1;
else if (PQntuples(res) <= 0)
{
PQclear(res);
descbuf[0] = '\0';
strcat(descbuf, "SELECT DISTINCT description ");
strcat(descbuf, "FROM pg_operator, pg_description ");
strcat(descbuf, "WHERE pg_operator.oprname = '");
strcat(descbuf, object);
strcat(descbuf, "'" );
strcat(descbuf, " and pg_operator.oid = pg_description.rowoid " );
if (!(res = PSQLexec(pset, descbuf)))
return -1;
else if (PQntuples(res) <= 0)
{
PQclear(res);
descbuf[0] = '\0';
strcat(descbuf, "SELECT DISTINCT description ");
strcat(descbuf, "FROM pg_aggregate, pg_description ");
strcat(descbuf, "WHERE pg_aggregate.aggname = '");
strcat(descbuf, object);
strcat(descbuf, "'" );
strcat(descbuf, " and pg_aggregate.oid = pg_description.rowoid " );
if (!(res = PSQLexec(pset, descbuf)))
return -1;
}
}
}
}
}
}
nDescriptions = PQntuples(res);
if (nDescriptions > 0)
{
if (fout == NULL)
{
if (pset->notty == 0 &&
(pagerenv = getenv("PAGER")) &&
pagerenv[0] != '\0' &&
screen_size.ws_row <= nDescriptions + 1 &&
(fout = popen(pagerenv, "w")))
{
usePipe = 1;
pqsignal(SIGPIPE, SIG_IGN);
}
else
fout = stdout;
}
/*
* * Display the information
*/
fprintf(fout,"\nObject = %s\n", object);
/* next, print out the instances */
for (i = 0; i < PQntuples(res); i++)
fprintf(fout,"%s\n",PQgetvalue(res, i, 0));
PQclear(res);
if (usePipe)
{
pclose(fout);
pqsignal(SIGPIPE, SIG_DFL);
}
return (0);
}
else
{
fprintf(stderr, "Couldn't find comments for object %s!\n", object);
return (-1);
}
}
typedef char *(*READ_ROUTINE) (char *prompt, FILE *source);
/*
@ -1505,31 +1698,29 @@ HandleSlashCmds(PsqlSettings *pset,
break;
case 'd': /* \d describe tables or columns in a
* table */
if (strncmp(cmd, "dt", 2) == 0)
{ /* only tables */
tableList(pset, false, 't');
}
if (strncmp(cmd, "dc", 2) == 0)
/* descriptions */
objectDescription(pset, optarg+1, NULL);
else if (strncmp(cmd, "di", 2) == 0)
{ /* only indices */
/* only indices */
tableList(pset, false, 'i');
}
else if (strncmp(cmd, "ds", 2) == 0)
{ /* only sequences */
/* only sequences */
tableList(pset, false, 'S');
}
else if (strncmp(cmd, "dt", 2) == 0)
/* only tables */
tableList(pset, false, 't');
else if (!optarg)
{ /* show tables, sequences and indices */
/* show tables, sequences and indices */
tableList(pset, false, 'b');
}
else if (strcmp(optarg, "*") == 0)
{ /* show everything */
if (tableList(pset, false, 'b') == 0)
tableList(pset, true, 'b');
}
else
{ /* describe the specified table */
/* describe the specified table */
tableDesc(pset, optarg, NULL);
}
break;
case 'e': /* edit */
{