diff options
Diffstat (limited to 'src/bin/psql/describe.c')
| -rw-r--r-- | src/bin/psql/describe.c | 1320 |
1 files changed, 681 insertions, 639 deletions
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 6304bc14ee8..58534e25751 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -4,7 +4,7 @@ #include <string.h> -#include <postgres.h> /* for VARHDRSZ, int4 type */ +#include <postgres.h> /* for VARHDRSZ, int4 type */ #include <postgres_ext.h> #include <libpq-fe.h> @@ -20,7 +20,7 @@ * * If you add something here, consider this: * - If (and only if) the variable "description" is set, the description/ - * comment for the object should be displayed. + * comment for the object should be displayed. * - Try to format the query to look nice in -E output. *---------------- */ @@ -34,61 +34,66 @@ * takes an optional regexp to match specific aggregates by name */ bool -describeAggregates(const char * name, PsqlSettings * pset) +describeAggregates(const char *name, PsqlSettings *pset) { - char descbuf[384 + 2*REGEXP_CUTOFF]; /* observe/adjust this if you change the query */ - PGresult * res; - bool description = GetVariableBool(pset->vars, "description"); - printQueryOpt myopt = pset->popt; - - descbuf[0] = '\0'; - - /* There are two kinds of aggregates: ones that work on particular types - ones that work on all */ - strcat(descbuf, - "SELECT a.aggname AS \"Name\", t.typname AS \"Type\""); - if (description) - strcat(descbuf, - ",\n obj_description(a.oid) as \"Description\""); - strcat(descbuf, - "\nFROM pg_aggregate a, pg_type t\n" - "WHERE a.aggbasetype = t.oid\n"); - if (name) { - strcat(descbuf, " AND a.aggname ~* '^"); - strncat(descbuf, name, REGEXP_CUTOFF); - strcat(descbuf, "'\n"); - } - - strcat(descbuf, - "UNION\n" - "SELECT a.aggname AS \"Name\", '(all types)' as \"Type\""); - if (description) - strcat(descbuf, - ",\n obj_description(a.oid) as \"Description\""); - strcat(descbuf, - "\nFROM pg_aggregate a\n" - "WHERE a.aggbasetype = 0\n"); - if (name) - { - strcat(descbuf, " AND a.aggname ~* '^"); - strncat(descbuf, name, REGEXP_CUTOFF); - strcat(descbuf, "'\n"); - } - - strcat(descbuf, "ORDER BY \"Name\", \"Type\""); - - res = PSQLexec(pset, descbuf); - if (!res) - return false; - - myopt.topt.tuples_only = false; - myopt.nullPrint = NULL; - myopt.title = "List of aggregates"; - - printQuery(res, &myopt, pset->queryFout); - - PQclear(res); - return true; + char descbuf[384 + 2 * REGEXP_CUTOFF]; /* observe/adjust this + * if you change the + * query */ + PGresult *res; + bool description = GetVariableBool(pset->vars, "description"); + printQueryOpt myopt = pset->popt; + + descbuf[0] = '\0'; + + /* + * There are two kinds of aggregates: ones that work on particular + * types ones that work on all + */ + strcat(descbuf, + "SELECT a.aggname AS \"Name\", t.typname AS \"Type\""); + if (description) + strcat(descbuf, + ",\n obj_description(a.oid) as \"Description\""); + strcat(descbuf, + "\nFROM pg_aggregate a, pg_type t\n" + "WHERE a.aggbasetype = t.oid\n"); + if (name) + { + strcat(descbuf, " AND a.aggname ~* '^"); + strncat(descbuf, name, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } + + strcat(descbuf, + "UNION\n" + "SELECT a.aggname AS \"Name\", '(all types)' as \"Type\""); + if (description) + strcat(descbuf, + ",\n obj_description(a.oid) as \"Description\""); + strcat(descbuf, + "\nFROM pg_aggregate a\n" + "WHERE a.aggbasetype = 0\n"); + if (name) + { + strcat(descbuf, " AND a.aggname ~* '^"); + strncat(descbuf, name, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } + + strcat(descbuf, "ORDER BY \"Name\", \"Type\""); + + res = PSQLexec(pset, descbuf); + if (!res) + return false; + + myopt.topt.tuples_only = false; + myopt.nullPrint = NULL; + myopt.title = "List of aggregates"; + + printQuery(res, &myopt, pset->queryFout); + + PQclear(res); + return true; } @@ -96,45 +101,44 @@ describeAggregates(const char * name, PsqlSettings * pset) * takes an optional regexp to narrow down the function name */ bool -describeFunctions(const char * name, PsqlSettings * pset) +describeFunctions(const char *name, PsqlSettings *pset) { - char descbuf[384 + REGEXP_CUTOFF]; - PGresult * res; - printQueryOpt myopt = pset->popt; - - /* - * we skip in/out funcs by excluding functions that take - * some arguments, but have no types defined for those - * arguments - */ - descbuf[0] = '\0'; - - strcat(descbuf, "SELECT t.typname as \"Result\", p.proname as \"Function\",\n" - " oid8types(p.proargtypes) as \"Arguments\""); - if (GetVariableBool(pset->vars, "description")) - strcat(descbuf, "\n, obj_description(p.oid) as \"Description\""); - strcat(descbuf, "\nFROM pg_proc p, pg_type t\n" - "WHERE p.prorettype = t.oid and (pronargs = 0 or oid8types(p.proargtypes) != '')\n"); - if (name) - { - strcat(descbuf, " AND p.proname ~* '^"); - strncat(descbuf, name, REGEXP_CUTOFF); - strcat(descbuf, "'\n"); - } - strcat(descbuf, "ORDER BY \"Function\", \"Result\", \"Arguments\""); - - res = PSQLexec(pset, descbuf); - if (!res) - return false; - - myopt.topt.tuples_only = false; - myopt.nullPrint = NULL; - myopt.title = "List of functions"; - - printQuery(res, &myopt, pset->queryFout); - - PQclear(res); - return true; + char descbuf[384 + REGEXP_CUTOFF]; + PGresult *res; + printQueryOpt myopt = pset->popt; + + /* + * we skip in/out funcs by excluding functions that take some + * arguments, but have no types defined for those arguments + */ + descbuf[0] = '\0'; + + strcat(descbuf, "SELECT t.typname as \"Result\", p.proname as \"Function\",\n" + " oid8types(p.proargtypes) as \"Arguments\""); + if (GetVariableBool(pset->vars, "description")) + strcat(descbuf, "\n, obj_description(p.oid) as \"Description\""); + strcat(descbuf, "\nFROM pg_proc p, pg_type t\n" + "WHERE p.prorettype = t.oid and (pronargs = 0 or oid8types(p.proargtypes) != '')\n"); + if (name) + { + strcat(descbuf, " AND p.proname ~* '^"); + strncat(descbuf, name, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } + strcat(descbuf, "ORDER BY \"Function\", \"Result\", \"Arguments\""); + + res = PSQLexec(pset, descbuf); + if (!res) + return false; + + myopt.topt.tuples_only = false; + myopt.nullPrint = NULL; + myopt.title = "List of functions"; + + printQuery(res, &myopt, pset->queryFout); + + PQclear(res); + return true; } @@ -145,38 +149,39 @@ describeFunctions(const char * name, PsqlSettings * pset) * for \dT */ bool -describeTypes(const char * name, PsqlSettings * pset) +describeTypes(const char *name, PsqlSettings *pset) { - char descbuf[256 + REGEXP_CUTOFF]; - PGresult * res; - printQueryOpt myopt = pset->popt; - - descbuf[0] = '\0'; - strcat(descbuf, "SELECT typname AS \"Type\""); - if (GetVariableBool(pset->vars, "description")) - strcat(descbuf, ", obj_description(p.oid) as \"Description\""); - strcat(descbuf, "\nFROM pg_type\n" - "WHERE typrelid = 0 AND typname !~ '^_.*'\n"); - - if (name) { - strcat(descbuf, " AND typname ~* '^"); - strncat(descbuf, name, REGEXP_CUTOFF); - strcat(descbuf, "' "); - } - strcat(descbuf, "ORDER BY typname;"); - - res = PSQLexec(pset, descbuf); - if (!res) - return false; - - myopt.topt.tuples_only = false; - myopt.nullPrint = NULL; - myopt.title = "List of types"; - - printQuery(res, &myopt, pset->queryFout); - - PQclear(res); - return true; + char descbuf[256 + REGEXP_CUTOFF]; + PGresult *res; + printQueryOpt myopt = pset->popt; + + descbuf[0] = '\0'; + strcat(descbuf, "SELECT typname AS \"Type\""); + if (GetVariableBool(pset->vars, "description")) + strcat(descbuf, ", obj_description(p.oid) as \"Description\""); + strcat(descbuf, "\nFROM pg_type\n" + "WHERE typrelid = 0 AND typname !~ '^_.*'\n"); + + if (name) + { + strcat(descbuf, " AND typname ~* '^"); + strncat(descbuf, name, REGEXP_CUTOFF); + strcat(descbuf, "' "); + } + strcat(descbuf, "ORDER BY typname;"); + + res = PSQLexec(pset, descbuf); + if (!res) + return false; + + myopt.topt.tuples_only = false; + myopt.nullPrint = NULL; + myopt.title = "List of types"; + + printQuery(res, &myopt, pset->queryFout); + + PQclear(res); + return true; } @@ -187,87 +192,88 @@ describeTypes(const char * name, PsqlSettings * pset) * exact match string. */ bool -describeOperators(const char * name, PsqlSettings * pset) +describeOperators(const char *name, PsqlSettings *pset) { - char descbuf[1536 + 3 * 32]; /* 32 is max length for operator name */ - PGresult * res; - bool description = GetVariableBool(pset->vars, "description"); - printQueryOpt myopt = pset->popt; - - descbuf[0] = '\0'; - - strcat(descbuf, "SELECT o.oprname AS \"Op\",\n" - " t1.typname AS \"Left arg\",\n" - " t2.typname AS \"Right arg\",\n" - " t0.typname AS \"Result\""); - if (description) - strcat(descbuf, ",\n obj_description(p.oid) as \"Description\""); - strcat(descbuf, "\nFROM pg_proc p, pg_type t0,\n" - " pg_type t1, pg_type t2,\n" - " pg_operator o\n" - "WHERE p.prorettype = t0.oid AND\n" - " RegprocToOid(o.oprcode) = p.oid AND\n" - " p.pronargs = 2 AND\n" - " o.oprleft = t1.oid AND\n" - " o.oprright = t2.oid\n"); - if (name) - { - strcat(descbuf, " AND o.oprname = '"); - strncat(descbuf, name, 32); - strcat(descbuf, "'\n"); - } - - strcat(descbuf, "\nUNION\n\n" - "SELECT o.oprname as \"Op\",\n" - " ''::name AS \"Left arg\",\n" - " t1.typname AS \"Right arg\",\n" - " t0.typname AS \"Result\""); - if (description) - strcat(descbuf, ",\n obj_description(p.oid) as \"Description\""); - strcat(descbuf, "\nFROM pg_operator o, pg_proc p, pg_type t0, pg_type t1\n" - "WHERE RegprocToOid(o.oprcode) = p.oid AND\n" - " o.oprresult = t0.oid AND\n" - " o.oprkind = 'l' AND\n" - " o.oprright = t1.oid\n"); - if (name) - { - strcat(descbuf, "AND o.oprname = '"); - strncat(descbuf, name, 32); - strcat(descbuf, "'\n"); - } - - strcat(descbuf, "\nUNION\n\n" - "SELECT o.oprname as \"Op\",\n" - " t1.typname AS \"Left arg\",\n" - " ''::name AS \"Right arg\",\n" - " t0.typname AS \"Result\""); - if (description) - strcat(descbuf, ",\n obj_description(p.oid) as \"Description\""); - strcat(descbuf, "\nFROM pg_operator o, pg_proc p, pg_type t0, pg_type t1\n" - "WHERE RegprocToOid(o.oprcode) = p.oid AND\n" - " o.oprresult = t0.oid AND\n" - " o.oprkind = 'r' AND\n" - " o.oprleft = t1.oid\n"); - if (name) - { - strcat(descbuf, "AND o.oprname = '"); - strncat(descbuf, name, 32); - strcat(descbuf, "'\n"); - } - strcat(descbuf, "\nORDER BY \"Op\", \"Left arg\", \"Right arg\", \"Result\""); - - res = PSQLexec(pset, descbuf); - if (!res) - return false; - - myopt.topt.tuples_only = false; - myopt.nullPrint = NULL; - myopt.title = "List of operators"; - - printQuery(res, &myopt, pset->queryFout); - - PQclear(res); - return true; + char descbuf[1536 + 3 * 32]; /* 32 is max length for operator + * name */ + PGresult *res; + bool description = GetVariableBool(pset->vars, "description"); + printQueryOpt myopt = pset->popt; + + descbuf[0] = '\0'; + + strcat(descbuf, "SELECT o.oprname AS \"Op\",\n" + " t1.typname AS \"Left arg\",\n" + " t2.typname AS \"Right arg\",\n" + " t0.typname AS \"Result\""); + if (description) + strcat(descbuf, ",\n obj_description(p.oid) as \"Description\""); + strcat(descbuf, "\nFROM pg_proc p, pg_type t0,\n" + " pg_type t1, pg_type t2,\n" + " pg_operator o\n" + "WHERE p.prorettype = t0.oid AND\n" + " RegprocToOid(o.oprcode) = p.oid AND\n" + " p.pronargs = 2 AND\n" + " o.oprleft = t1.oid AND\n" + " o.oprright = t2.oid\n"); + if (name) + { + strcat(descbuf, " AND o.oprname = '"); + strncat(descbuf, name, 32); + strcat(descbuf, "'\n"); + } + + strcat(descbuf, "\nUNION\n\n" + "SELECT o.oprname as \"Op\",\n" + " ''::name AS \"Left arg\",\n" + " t1.typname AS \"Right arg\",\n" + " t0.typname AS \"Result\""); + if (description) + strcat(descbuf, ",\n obj_description(p.oid) as \"Description\""); + strcat(descbuf, "\nFROM pg_operator o, pg_proc p, pg_type t0, pg_type t1\n" + "WHERE RegprocToOid(o.oprcode) = p.oid AND\n" + " o.oprresult = t0.oid AND\n" + " o.oprkind = 'l' AND\n" + " o.oprright = t1.oid\n"); + if (name) + { + strcat(descbuf, "AND o.oprname = '"); + strncat(descbuf, name, 32); + strcat(descbuf, "'\n"); + } + + strcat(descbuf, "\nUNION\n\n" + "SELECT o.oprname as \"Op\",\n" + " t1.typname AS \"Left arg\",\n" + " ''::name AS \"Right arg\",\n" + " t0.typname AS \"Result\""); + if (description) + strcat(descbuf, ",\n obj_description(p.oid) as \"Description\""); + strcat(descbuf, "\nFROM pg_operator o, pg_proc p, pg_type t0, pg_type t1\n" + "WHERE RegprocToOid(o.oprcode) = p.oid AND\n" + " o.oprresult = t0.oid AND\n" + " o.oprkind = 'r' AND\n" + " o.oprleft = t1.oid\n"); + if (name) + { + strcat(descbuf, "AND o.oprname = '"); + strncat(descbuf, name, 32); + strcat(descbuf, "'\n"); + } + strcat(descbuf, "\nORDER BY \"Op\", \"Left arg\", \"Right arg\", \"Result\""); + + res = PSQLexec(pset, descbuf); + if (!res) + return false; + + myopt.topt.tuples_only = false; + myopt.nullPrint = NULL; + myopt.title = "List of operators"; + + printQuery(res, &myopt, pset->queryFout); + + PQclear(res); + return true; } @@ -279,81 +285,82 @@ describeOperators(const char * name, PsqlSettings * pset) bool listAllDbs(PsqlSettings *pset) { - PGresult *res; - char descbuf[256]; - printQueryOpt myopt = pset->popt; + PGresult *res; + char descbuf[256]; + printQueryOpt myopt = pset->popt; - descbuf[0] = '\0'; - strcat(descbuf, "SELECT pg_database.datname as \"Database\",\n" - " pg_user.usename as \"Owner\"" + descbuf[0] = '\0'; + strcat(descbuf, "SELECT pg_database.datname as \"Database\",\n" + " pg_user.usename as \"Owner\"" #ifdef MULTIBYTE - ",\n pg_database.encoding as \"Encoding\"" + ",\n pg_database.encoding as \"Encoding\"" #endif - ); - if (GetVariableBool(pset->vars, "description")) - strcat(descbuf, ",\n obj_description(pg_database.oid) as \"Description\"\n"); - strcat(descbuf, "FROM pg_database, pg_user\n" - "WHERE pg_database.datdba = pg_user.usesysid\n" - "ORDER BY \"Database\""); + ); + if (GetVariableBool(pset->vars, "description")) + strcat(descbuf, ",\n obj_description(pg_database.oid) as \"Description\"\n"); + strcat(descbuf, "FROM pg_database, pg_user\n" + "WHERE pg_database.datdba = pg_user.usesysid\n" + "ORDER BY \"Database\""); - res = PSQLexec(pset, descbuf); - if (!res) - return false; + res = PSQLexec(pset, descbuf); + if (!res) + return false; - myopt.topt.tuples_only = false; - myopt.nullPrint = NULL; - myopt.title = "List of databases"; + myopt.topt.tuples_only = false; + myopt.nullPrint = NULL; + myopt.title = "List of databases"; - printQuery(res, &myopt, pset->queryFout); + printQuery(res, &myopt, pset->queryFout); - PQclear(res); - return true; + PQclear(res); + return true; } /* List Tables Grant/Revoke Permissions * \z (now also \dp -- perhaps more mnemonic) - * + * */ bool -permissionsList(const char * name, PsqlSettings *pset) +permissionsList(const char *name, PsqlSettings *pset) { - char descbuf[256 + REGEXP_CUTOFF]; - PGresult *res; - printQueryOpt myopt = pset->popt; - - descbuf[0] = '\0'; - /* Currently, we ignore indexes since they have no meaningful rights */ - strcat(descbuf, "SELECT relname as \"Relation\",\n" - " relacl as \"Access permissions\"\n" - "FROM pg_class\n" - "WHERE ( relkind = 'r' OR relkind = 'S') AND\n" - " relname !~ '^pg_'\n"); - if (name) { - strcat(descbuf, " AND rename ~ '^"); - strncat(descbuf, name, REGEXP_CUTOFF); - strcat(descbuf, "'\n"); - } - strcat (descbuf, "ORDER BY relname"); - - res = PSQLexec(pset, descbuf); - if (!res) - return false; - - if (PQntuples(res) == 0) { - fputs("Couldn't find any tables.\n", pset->queryFout); - } - else { - myopt.topt.tuples_only = false; - myopt.nullPrint = NULL; - sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset->db)); - myopt.title = descbuf; + char descbuf[256 + REGEXP_CUTOFF]; + PGresult *res; + printQueryOpt myopt = pset->popt; + + descbuf[0] = '\0'; + /* Currently, we ignore indexes since they have no meaningful rights */ + strcat(descbuf, "SELECT relname as \"Relation\",\n" + " relacl as \"Access permissions\"\n" + "FROM pg_class\n" + "WHERE ( relkind = 'r' OR relkind = 'S') AND\n" + " relname !~ '^pg_'\n"); + if (name) + { + strcat(descbuf, " AND rename ~ '^"); + strncat(descbuf, name, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } + strcat(descbuf, "ORDER BY relname"); - printQuery(res, &myopt, pset->queryFout); - } + res = PSQLexec(pset, descbuf); + if (!res) + return false; + + if (PQntuples(res) == 0) + fputs("Couldn't find any tables.\n", pset->queryFout); + else + { + myopt.topt.tuples_only = false; + myopt.nullPrint = NULL; + sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset->db)); + myopt.title = descbuf; - PQclear(res); - return true; + printQuery(res, &myopt, pset->queryFout); + } + + PQclear(res); + return true; } @@ -368,106 +375,113 @@ permissionsList(const char * name, PsqlSettings *pset) * lists of things, there are other \d? commands. */ bool -objectDescription(const char * object, PsqlSettings *pset) +objectDescription(const char *object, PsqlSettings *pset) { - char descbuf[2048 + 7*REGEXP_CUTOFF]; - PGresult *res; - printQueryOpt myopt = pset->popt; - - descbuf[0] = '\0'; - - /* Aggregate descriptions */ - strcat(descbuf, "SELECT DISTINCT a.aggname as \"Name\", 'aggregate'::text as \"What\", d.description as \"Description\"\n" - "FROM pg_aggregate a, pg_description d\n" - "WHERE a.oid = d.objoid\n"); - if (object) { - strcat(descbuf," AND a.aggname ~* '^"); - strncat(descbuf, object, REGEXP_CUTOFF); - strcat(descbuf,"'\n"); - } - - /* Function descriptions (except in/outs for datatypes) */ - strcat(descbuf, "\nUNION ALL\n\n"); - strcat(descbuf, "SELECT DISTINCT p.proname as \"Name\", 'function'::text as \"What\", d.description as \"Description\"\n" - "FROM pg_proc p, pg_description d\n" - "WHERE p.oid = d.objoid AND (p.pronargs = 0 or oid8types(p.proargtypes) != '')\n"); - if (object) { - strcat(descbuf," AND p.proname ~* '^"); - strncat(descbuf, object, REGEXP_CUTOFF); - strcat(descbuf,"'\n"); - } - - /* Operator descriptions */ - strcat(descbuf, "\nUNION ALL\n\n"); - strcat(descbuf, "SELECT DISTINCT o.oprname as \"Name\", 'operator'::text as \"What\", d.description as \"Description\"\n" - "FROM pg_operator o, pg_description d\n" - // must get comment via associated function - "WHERE RegprocToOid(o.oprcode) = d.objoid\n"); - if (object) { - strcat(descbuf," AND o.oprname = '"); - strncat(descbuf, object, REGEXP_CUTOFF); - strcat(descbuf,"'\n"); - } - - /* Type description */ - strcat(descbuf, "\nUNION ALL\n\n"); - strcat(descbuf, "SELECT DISTINCT t.typname as \"Name\", 'type'::text as \"What\", d.description as \"Description\"\n" - "FROM pg_type t, pg_description d\n" - "WHERE t.oid = d.objoid\n"); - if (object) { - strcat(descbuf," AND t.typname ~* '^"); - strncat(descbuf, object, REGEXP_CUTOFF); - strcat(descbuf,"'\n"); - } - - /* Relation (tables, views, indices, sequences) descriptions */ - strcat(descbuf, "\nUNION ALL\n\n"); - strcat(descbuf, "SELECT DISTINCT c.relname as \"Name\", 'relation'::text||'('||c.relkind||')' as \"What\", d.description as \"Description\"\n" - "FROM pg_class c, pg_description d\n" - "WHERE c.oid = d.objoid\n"); - if (object) { - strcat(descbuf," AND c.relname ~* '^"); - strncat(descbuf, object, REGEXP_CUTOFF); - strcat(descbuf,"'\n"); - } - - /* Rule description (ignore rules for views) */ - strcat(descbuf, "\nUNION ALL\n\n"); - strcat(descbuf, "SELECT DISTINCT r.rulename as \"Name\", 'rule'::text as \"What\", d.description as \"Description\"\n" - "FROM pg_rewrite r, pg_description d\n" - "WHERE r.oid = d.objoid AND r.rulename !~ '^_RET'\n"); - if (object) { - strcat(descbuf," AND r.rulename ~* '^"); - strncat(descbuf, object, REGEXP_CUTOFF); - strcat(descbuf,"'\n"); - } - - /* Trigger description */ - strcat(descbuf, "\nUNION ALL\n\n"); - strcat(descbuf, "SELECT DISTINCT t.tgname as \"Name\", 'trigger'::text as \"What\", d.description as \"Description\"\n" - "FROM pg_trigger t, pg_description d\n" - "WHERE t.oid = d.objoid\n"); - if (object) { - strcat(descbuf," AND t.tgname ~* '^"); - strncat(descbuf, object, REGEXP_CUTOFF); - strcat(descbuf,"'\n"); - } - - strcat(descbuf, "\nORDER BY \"Name\""); - - - res = PSQLexec(pset, descbuf); - if (!res) - return false; - - myopt.topt.tuples_only = false; - myopt.nullPrint = NULL; - myopt.title = "Object descriptions"; - - printQuery(res, &myopt, pset->queryFout); - - PQclear(res); - return true; + char descbuf[2048 + 7 * REGEXP_CUTOFF]; + PGresult *res; + printQueryOpt myopt = pset->popt; + + descbuf[0] = '\0'; + + /* Aggregate descriptions */ + strcat(descbuf, "SELECT DISTINCT a.aggname as \"Name\", 'aggregate'::text as \"What\", d.description as \"Description\"\n" + "FROM pg_aggregate a, pg_description d\n" + "WHERE a.oid = d.objoid\n"); + if (object) + { + strcat(descbuf, " AND a.aggname ~* '^"); + strncat(descbuf, object, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } + + /* Function descriptions (except in/outs for datatypes) */ + strcat(descbuf, "\nUNION ALL\n\n"); + strcat(descbuf, "SELECT DISTINCT p.proname as \"Name\", 'function'::text as \"What\", d.description as \"Description\"\n" + "FROM pg_proc p, pg_description d\n" + "WHERE p.oid = d.objoid AND (p.pronargs = 0 or oid8types(p.proargtypes) != '')\n"); + if (object) + { + strcat(descbuf, " AND p.proname ~* '^"); + strncat(descbuf, object, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } + + /* Operator descriptions */ + strcat(descbuf, "\nUNION ALL\n\n"); + strcat(descbuf, "SELECT DISTINCT o.oprname as \"Name\", 'operator'::text as \"What\", d.description as \"Description\"\n" + "FROM pg_operator o, pg_description d\n" + // must get comment via associated function + "WHERE RegprocToOid(o.oprcode) = d.objoid\n"); + if (object) + { + strcat(descbuf, " AND o.oprname = '"); + strncat(descbuf, object, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } + + /* Type description */ + strcat(descbuf, "\nUNION ALL\n\n"); + strcat(descbuf, "SELECT DISTINCT t.typname as \"Name\", 'type'::text as \"What\", d.description as \"Description\"\n" + "FROM pg_type t, pg_description d\n" + "WHERE t.oid = d.objoid\n"); + if (object) + { + strcat(descbuf, " AND t.typname ~* '^"); + strncat(descbuf, object, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } + + /* Relation (tables, views, indices, sequences) descriptions */ + strcat(descbuf, "\nUNION ALL\n\n"); + strcat(descbuf, "SELECT DISTINCT c.relname as \"Name\", 'relation'::text||'('||c.relkind||')' as \"What\", d.description as \"Description\"\n" + "FROM pg_class c, pg_description d\n" + "WHERE c.oid = d.objoid\n"); + if (object) + { + strcat(descbuf, " AND c.relname ~* '^"); + strncat(descbuf, object, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } + + /* Rule description (ignore rules for views) */ + strcat(descbuf, "\nUNION ALL\n\n"); + strcat(descbuf, "SELECT DISTINCT r.rulename as \"Name\", 'rule'::text as \"What\", d.description as \"Description\"\n" + "FROM pg_rewrite r, pg_description d\n" + "WHERE r.oid = d.objoid AND r.rulename !~ '^_RET'\n"); + if (object) + { + strcat(descbuf, " AND r.rulename ~* '^"); + strncat(descbuf, object, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } + + /* Trigger description */ + strcat(descbuf, "\nUNION ALL\n\n"); + strcat(descbuf, "SELECT DISTINCT t.tgname as \"Name\", 'trigger'::text as \"What\", d.description as \"Description\"\n" + "FROM pg_trigger t, pg_description d\n" + "WHERE t.oid = d.objoid\n"); + if (object) + { + strcat(descbuf, " AND t.tgname ~* '^"); + strncat(descbuf, object, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } + + strcat(descbuf, "\nORDER BY \"Name\""); + + + res = PSQLexec(pset, descbuf); + if (!res) + return false; + + myopt.topt.tuples_only = false; + myopt.nullPrint = NULL; + myopt.title = "Object descriptions"; + + printQuery(res, &myopt, pset->queryFout); + + PQclear(res); + return true; } @@ -480,199 +494,218 @@ objectDescription(const char * object, PsqlSettings *pset) * and pass it to the underlying printTable() function. * */ -static void * xmalloc(size_t size) +static void * +xmalloc(size_t size) { - void * tmp; - tmp = malloc(size); - if (!tmp) { - perror("malloc"); - exit(EXIT_FAILURE); - } - return tmp; + void *tmp; + + tmp = malloc(size); + if (!tmp) + { + perror("malloc"); + exit(EXIT_FAILURE); + } + return tmp; } bool -describeTableDetails(const char * name, PsqlSettings * pset) +describeTableDetails(const char *name, PsqlSettings *pset) { - char descbuf[512 + NAMEDATALEN]; - PGresult *res = NULL, *res2 = NULL, *res3 = NULL; - printTableOpt myopt = pset->popt.topt; - bool description = GetVariableBool(pset->vars, "description"); - int i; - char * view_def = NULL; - char * headers[5]; - char ** cells = NULL; - char * title = NULL; - char ** footers = NULL; - char ** ptr; - unsigned int cols; - - cols = 3 + (description ? 1 : 0); - - headers[0] = "Attribute"; - headers[1] = "Type"; - headers[2] = "Info"; - if (description) { - headers[3] = "Description"; - headers[4] = NULL; - } - else - headers[3] = NULL; - - /* Get general table info */ - strcpy(descbuf, "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum"); - if (description) - strcat(descbuf, ", obj_description(a.oid)"); - strcat(descbuf, "\nFROM pg_class c, pg_attribute a, pg_type t\n" - "WHERE c.relname = '"); - strncat(descbuf, name, NAMEDATALEN); - strcat(descbuf, "'\n AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid\n" - "ORDER BY a.attnum"); - - res = PSQLexec(pset, descbuf); - if (!res) - return false; - - /* Did we get anything? */ - if (PQntuples(res)==0) { - if (!GetVariableBool(pset->vars, "quiet")) - fprintf(stdout, "Did not find any class named \"%s\".\n", name); - PQclear(res); - return false; - } - - /* Check if table is a view */ - strcpy(descbuf, "SELECT definition FROM pg_views WHERE viewname = '"); - strncat(descbuf, name, NAMEDATALEN); - strcat(descbuf, "'"); - res2 = PSQLexec(pset, descbuf); - if (!res2) - return false; - - if (PQntuples(res2) > 0) - view_def = PQgetvalue(res2,0,0); - - - - /* Generate table cells to be printed */ - cells = calloc(PQntuples(res) * cols + 1, sizeof(*cells)); - if (!cells) { - perror("calloc"); - exit(EXIT_FAILURE); - } - - for (i = 0; i < PQntuples(res); i++) { - int4 attypmod = atoi(PQgetvalue(res, i, 3)); - char * attype = PQgetvalue(res, i, 1); - - /* Name */ - cells[i*cols + 0] = PQgetvalue(res, i, 0); /* don't free this afterwards */ - - /* Type */ - cells[i*cols + 1] = xmalloc(NAMEDATALEN + 16); - if (strcmp(attype, "bpchar")==0) - sprintf(cells[i*cols + 1], "char(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0); - else if (strcmp(attype, "varchar")==0) - sprintf(cells[i*cols + 1], "varchar(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0); - else if (strcmp(attype, "numeric")==0) - sprintf(cells[i*cols + 1], "numeric(%d,%d)", ((attypmod - VARHDRSZ) >> 16) & 0xffff, - (attypmod - VARHDRSZ) & 0xffff ); - else if (attype[0] == '_') - sprintf(cells[i*cols + 1], "%s[]", attype+1); - else - strcpy(cells[i*cols + 1], attype); - - /* Info */ - cells[i*cols + 2] = xmalloc(128 + 128); /* I'm cutting off the default string at 128 */ - cells[i*cols + 2][0] = '\0'; - if (strcmp(PQgetvalue(res, i, 4), "t") == 0) - strcat(cells[i*cols + 2], "not null"); - if (strcmp(PQgetvalue(res, i, 5), "t") == 0) { - /* handle "default" here */ - strcpy(descbuf, "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n" - "WHERE c.relname = '"); - strncat(descbuf, name, NAMEDATALEN); - strcat(descbuf, "' AND c.oid = d.adrelid AND d.adnum = "); - strcat(descbuf, PQgetvalue(res, i, 6)); - - res3 = PSQLexec(pset, descbuf); - if (!res) return false; - if (cells[i*cols+2][0]) strcat(cells[i*cols+2], " "); - strcat(cells[i*cols + 2], "default "); - strcat(cells[i*cols + 2], PQgetvalue(res3, 0, 0)); + char descbuf[512 + NAMEDATALEN]; + PGresult *res = NULL, + *res2 = NULL, + *res3 = NULL; + printTableOpt myopt = pset->popt.topt; + bool description = GetVariableBool(pset->vars, "description"); + int i; + char *view_def = NULL; + char *headers[5]; + char **cells = NULL; + char *title = NULL; + char **footers = NULL; + char **ptr; + unsigned int cols; + + cols = 3 + (description ? 1 : 0); + + headers[0] = "Attribute"; + headers[1] = "Type"; + headers[2] = "Info"; + if (description) + { + headers[3] = "Description"; + headers[4] = NULL; } + else + headers[3] = NULL; - /* Description */ + /* Get general table info */ + strcpy(descbuf, "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum"); if (description) - cells[i*cols + 3] = PQgetvalue(res, i, 7); - } - - /* Make title */ - title = xmalloc(10 + strlen(name)); - if (view_def) - sprintf(title, "View \"%s\"", name); - else - sprintf(title, "Table \"%s\"", name); - - /* Make footers */ - if (view_def) { - footers = xmalloc(2 * sizeof(*footers)); - footers[0] = xmalloc(20 + strlen(view_def)); - sprintf(footers[0], "View definition: %s", view_def); - footers[1] = NULL; - } - else { - /* display indices */ - strcpy(descbuf, "SELECT c2.relname\n" - "FROM pg_class c, pg_class c2, pg_index i\n" - "WHERE c.relname = '"); + strcat(descbuf, ", obj_description(a.oid)"); + strcat(descbuf, "\nFROM pg_class c, pg_attribute a, pg_type t\n" + "WHERE c.relname = '"); + strncat(descbuf, name, NAMEDATALEN); + strcat(descbuf, "'\n AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid\n" + "ORDER BY a.attnum"); + + res = PSQLexec(pset, descbuf); + if (!res) + return false; + + /* Did we get anything? */ + if (PQntuples(res) == 0) + { + if (!GetVariableBool(pset->vars, "quiet")) + fprintf(stdout, "Did not find any class named \"%s\".\n", name); + PQclear(res); + return false; + } + + /* Check if table is a view */ + strcpy(descbuf, "SELECT definition FROM pg_views WHERE viewname = '"); strncat(descbuf, name, NAMEDATALEN); - strcat(descbuf, "' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n" - "ORDER BY c2.relname"); - res3 = PSQLexec(pset, descbuf); - if (!res3) - return false; - - if (PQntuples(res3) > 0) { - footers = xmalloc((PQntuples(res3) + 1) * sizeof(*footers)); - - for (i=0; i<PQntuples(res3); i++) { - footers[i] = xmalloc(10 + NAMEDATALEN); - if (PQntuples(res3)==1) - sprintf(footers[i], "Index: %s", PQgetvalue(res3, i, 0)); - else if (i==0) - sprintf(footers[i], "Indices: %s", PQgetvalue(res3, i, 0)); + strcat(descbuf, "'"); + res2 = PSQLexec(pset, descbuf); + if (!res2) + return false; + + if (PQntuples(res2) > 0) + view_def = PQgetvalue(res2, 0, 0); + + + + /* Generate table cells to be printed */ + cells = calloc(PQntuples(res) * cols + 1, sizeof(*cells)); + if (!cells) + { + perror("calloc"); + exit(EXIT_FAILURE); + } + + for (i = 0; i < PQntuples(res); i++) + { + int4 attypmod = atoi(PQgetvalue(res, i, 3)); + char *attype = PQgetvalue(res, i, 1); + + /* Name */ + cells[i * cols + 0] = PQgetvalue(res, i, 0); /* don't free this + * afterwards */ + + /* Type */ + cells[i * cols + 1] = xmalloc(NAMEDATALEN + 16); + if (strcmp(attype, "bpchar") == 0) + sprintf(cells[i * cols + 1], "char(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0); + else if (strcmp(attype, "varchar") == 0) + sprintf(cells[i * cols + 1], "varchar(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0); + else if (strcmp(attype, "numeric") == 0) + sprintf(cells[i * cols + 1], "numeric(%d,%d)", ((attypmod - VARHDRSZ) >> 16) & 0xffff, + (attypmod - VARHDRSZ) & 0xffff); + else if (attype[0] == '_') + sprintf(cells[i * cols + 1], "%s[]", attype + 1); else - sprintf(footers[i], " %s", PQgetvalue(res3, i, 0)); - } + strcpy(cells[i * cols + 1], attype); + + /* Info */ + cells[i * cols + 2] = xmalloc(128 + 128); /* I'm cutting off the + * default string at 128 */ + cells[i * cols + 2][0] = '\0'; + if (strcmp(PQgetvalue(res, i, 4), "t") == 0) + strcat(cells[i * cols + 2], "not null"); + if (strcmp(PQgetvalue(res, i, 5), "t") == 0) + { + /* handle "default" here */ + strcpy(descbuf, "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n" + "WHERE c.relname = '"); + strncat(descbuf, name, NAMEDATALEN); + strcat(descbuf, "' AND c.oid = d.adrelid AND d.adnum = "); + strcat(descbuf, PQgetvalue(res, i, 6)); + + res3 = PSQLexec(pset, descbuf); + if (!res) + return false; + if (cells[i * cols + 2][0]) + strcat(cells[i * cols + 2], " "); + strcat(cells[i * cols + 2], "default "); + strcat(cells[i * cols + 2], PQgetvalue(res3, 0, 0)); + } + + /* Description */ + if (description) + cells[i * cols + 3] = PQgetvalue(res, i, 7); + } - footers[i] = NULL; + /* Make title */ + title = xmalloc(10 + strlen(name)); + if (view_def) + sprintf(title, "View \"%s\"", name); + else + sprintf(title, "Table \"%s\"", name); + + /* Make footers */ + if (view_def) + { + footers = xmalloc(2 * sizeof(*footers)); + footers[0] = xmalloc(20 + strlen(view_def)); + sprintf(footers[0], "View definition: %s", view_def); + footers[1] = NULL; + } + else + { + /* display indices */ + strcpy(descbuf, "SELECT c2.relname\n" + "FROM pg_class c, pg_class c2, pg_index i\n" + "WHERE c.relname = '"); + strncat(descbuf, name, NAMEDATALEN); + strcat(descbuf, "' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n" + "ORDER BY c2.relname"); + res3 = PSQLexec(pset, descbuf); + if (!res3) + return false; + + if (PQntuples(res3) > 0) + { + footers = xmalloc((PQntuples(res3) + 1) * sizeof(*footers)); + + for (i = 0; i < PQntuples(res3); i++) + { + footers[i] = xmalloc(10 + NAMEDATALEN); + if (PQntuples(res3) == 1) + sprintf(footers[i], "Index: %s", PQgetvalue(res3, i, 0)); + else if (i == 0) + sprintf(footers[i], "Indices: %s", PQgetvalue(res3, i, 0)); + else + sprintf(footers[i], " %s", PQgetvalue(res3, i, 0)); + } + + footers[i] = NULL; + } } - } - myopt.tuples_only = false; - printTable(title, headers, cells, footers, "llll", &myopt, pset->queryFout); + myopt.tuples_only = false; + printTable(title, headers, cells, footers, "llll", &myopt, pset->queryFout); - /* clean up */ - free(title); + /* clean up */ + free(title); - for (i = 0; i<PQntuples(res); i++) { - free(cells[i*cols + 1]); - free(cells[i*cols + 2]); - } - free(cells); + for (i = 0; i < PQntuples(res); i++) + { + free(cells[i * cols + 1]); + free(cells[i * cols + 2]); + } + free(cells); - for (ptr = footers; footers && *ptr; ptr++) - free(*ptr); - free(footers); + for (ptr = footers; footers && *ptr; ptr++) + free(*ptr); + free(footers); - PQclear(res); - PQclear(res2); - PQclear(res3); + PQclear(res); + PQclear(res2); + PQclear(res3); - return true; + return true; } @@ -691,125 +724,134 @@ describeTableDetails(const char * name, PsqlSettings * pset) * (any order of the above is fine) */ bool -listTables(const char * infotype, const char * name, PsqlSettings * pset) +listTables(const char *infotype, const char *name, PsqlSettings *pset) { - bool showTables = strchr(infotype, 't') != NULL; - bool showIndices= strchr(infotype, 'i') != NULL; - bool showViews = strchr(infotype, 'v') != NULL; - bool showSeq = strchr(infotype, 's') != NULL; - bool showSystem = strchr(infotype, 'S') != NULL; - - bool description = GetVariableBool(pset->vars, "description"); - - char descbuf[1536 + 4 * REGEXP_CUTOFF]; - PGresult *res; - printQueryOpt myopt = pset->popt; - - descbuf[0] = '\0'; - - /* tables */ - if (showTables) { - strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'table'::text as \"Type\""); - if (description) - strcat(descbuf, ", obj_description(c.oid) as \"Description\""); - strcat(descbuf, "\nFROM pg_class c, pg_user u\n" - "WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n" - " AND not exists (select 1 from pg_views where viewname = c.relname)\n"); - strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n"); - if (name) { - strcat(descbuf, " AND c.relname ~ '^"); - strncat(descbuf, name, REGEXP_CUTOFF); - strcat(descbuf, "'\n"); + bool showTables = strchr(infotype, 't') != NULL; + bool showIndices = strchr(infotype, 'i') != NULL; + bool showViews = strchr(infotype, 'v') != NULL; + bool showSeq = strchr(infotype, 's') != NULL; + bool showSystem = strchr(infotype, 'S') != NULL; + + bool description = GetVariableBool(pset->vars, "description"); + + char descbuf[1536 + 4 * REGEXP_CUTOFF]; + PGresult *res; + printQueryOpt myopt = pset->popt; + + descbuf[0] = '\0'; + + /* tables */ + if (showTables) + { + strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'table'::text as \"Type\""); + if (description) + strcat(descbuf, ", obj_description(c.oid) as \"Description\""); + strcat(descbuf, "\nFROM pg_class c, pg_user u\n" + "WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n" + " AND not exists (select 1 from pg_views where viewname = c.relname)\n"); + strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n"); + if (name) + { + strcat(descbuf, " AND c.relname ~ '^"); + strncat(descbuf, name, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } } - } - - /* views */ - if (showViews) { - if (descbuf[0]) - strcat(descbuf, "\nUNION\n\n"); - strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'view'::text as \"Type\""); - if (description) - strcat(descbuf, ", obj_description(c.oid) as \"Description\""); - strcat(descbuf, "\nFROM pg_class c, pg_user u\n" - "WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n" - " AND exists (select 1 from pg_views where viewname = c.relname)\n"); - strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n"); - if (name) { - strcat(descbuf, " AND c.relname ~ '^"); - strncat(descbuf, name, REGEXP_CUTOFF); - strcat(descbuf, "'\n"); + /* views */ + if (showViews) + { + if (descbuf[0]) + strcat(descbuf, "\nUNION\n\n"); + + strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'view'::text as \"Type\""); + if (description) + strcat(descbuf, ", obj_description(c.oid) as \"Description\""); + strcat(descbuf, "\nFROM pg_class c, pg_user u\n" + "WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n" + " AND exists (select 1 from pg_views where viewname = c.relname)\n"); + strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n"); + if (name) + { + strcat(descbuf, " AND c.relname ~ '^"); + strncat(descbuf, name, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } } - } - - /* indices, sequences */ - if (showIndices || showSeq) { - if (descbuf[0]) - strcat(descbuf, "\nUNION\n\n"); - strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\",\n" - " (CASE WHEN relkind = 'S' THEN 'sequence'::text ELSE 'index'::text END) as \"Type\""); - if (description) - strcat(descbuf, ", obj_description(c.oid) as \"Description\""); - strcat(descbuf, "\nFROM pg_class c, pg_user u\n" - "WHERE c.relowner = u.usesysid AND relkind in ("); - if (showIndices && showSeq) - strcat(descbuf, "'i', 'S'"); - else if (showIndices) - strcat(descbuf, "'i'"); - else - strcat(descbuf, "'S'"); - strcat(descbuf, ")\n"); - - /* ignore large-obj indices */ - if (showIndices) - strcat(descbuf, " AND (c.relkind != 'i' OR c.relname !~ '^xinx')\n"); - - strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n"); - if (name) { - strcat(descbuf, " AND c.relname ~ '^"); - strncat(descbuf, name, REGEXP_CUTOFF); - strcat(descbuf, "'\n"); + /* indices, sequences */ + if (showIndices || showSeq) + { + if (descbuf[0]) + strcat(descbuf, "\nUNION\n\n"); + + strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\",\n" + " (CASE WHEN relkind = 'S' THEN 'sequence'::text ELSE 'index'::text END) as \"Type\""); + if (description) + strcat(descbuf, ", obj_description(c.oid) as \"Description\""); + strcat(descbuf, "\nFROM pg_class c, pg_user u\n" + "WHERE c.relowner = u.usesysid AND relkind in ("); + if (showIndices && showSeq) + strcat(descbuf, "'i', 'S'"); + else if (showIndices) + strcat(descbuf, "'i'"); + else + strcat(descbuf, "'S'"); + strcat(descbuf, ")\n"); + + /* ignore large-obj indices */ + if (showIndices) + strcat(descbuf, " AND (c.relkind != 'i' OR c.relname !~ '^xinx')\n"); + + strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n"); + if (name) + { + strcat(descbuf, " AND c.relname ~ '^"); + strncat(descbuf, name, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } } - } - - /* real system catalogue tables */ - if (showSystem && showTables) { - if (descbuf[0]) - strcat(descbuf, "\nUNION\n\n"); - strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'system'::text as \"Type\""); - if (description) - strcat(descbuf, ", obj_description(c.oid) as \"Description\""); - strcat(descbuf, "\nFROM pg_class c, pg_user u\n" - "WHERE c.relowner = u.usesysid AND c.relkind = 's'\n"); - if (name) { - strcat(descbuf, " AND c.relname ~ '^"); - strncat(descbuf, name, REGEXP_CUTOFF); - strcat(descbuf, "'\n"); + /* real system catalogue tables */ + if (showSystem && showTables) + { + if (descbuf[0]) + strcat(descbuf, "\nUNION\n\n"); + + strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'system'::text as \"Type\""); + if (description) + strcat(descbuf, ", obj_description(c.oid) as \"Description\""); + strcat(descbuf, "\nFROM pg_class c, pg_user u\n" + "WHERE c.relowner = u.usesysid AND c.relkind = 's'\n"); + if (name) + { + strcat(descbuf, " AND c.relname ~ '^"); + strncat(descbuf, name, REGEXP_CUTOFF); + strcat(descbuf, "'\n"); + } } - } - strcat(descbuf, "\nORDER BY \"Name\""); + strcat(descbuf, "\nORDER BY \"Name\""); - res = PSQLexec(pset, descbuf); - if (!res) - return false; + res = PSQLexec(pset, descbuf); + if (!res) + return false; - if (PQntuples(res) == 0) - fprintf(pset->queryFout, "No matching classes found.\n"); + if (PQntuples(res) == 0) + fprintf(pset->queryFout, "No matching classes found.\n"); - else { - myopt.topt.tuples_only = false; - myopt.nullPrint = NULL; - myopt.title = "List of classes"; + else + { + myopt.topt.tuples_only = false; + myopt.nullPrint = NULL; + myopt.title = "List of classes"; - printQuery(res, &myopt, pset->queryFout); - } + printQuery(res, &myopt, pset->queryFout); + } - PQclear(res); - return true; + PQclear(res); + return true; } |
