aboutsummaryrefslogtreecommitdiff
path: root/src/bin/psql/psql.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/psql/psql.c')
-rw-r--r--src/bin/psql/psql.c235
1 files changed, 213 insertions, 22 deletions
diff --git a/src/bin/psql/psql.c b/src/bin/psql/psql.c
index db178743883..8b2a993c434 100644
--- a/src/bin/psql/psql.c
+++ b/src/bin/psql/psql.c
@@ -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 */
{