mirror of
https://github.com/postgres/postgres.git
synced 2025-06-22 02:52:08 +03:00
Remove traces of NAMEDATALEN and INDEX_MAX_KEYS from psql. Build buffers
dynamically with PQExpBuffer.
This commit is contained in:
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright 2000 by PostgreSQL Global Development Group
|
* Copyright 2000 by PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.71 2002/03/27 19:16:13 petere Exp $
|
* $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.72 2002/04/24 05:24:00 petere Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
@ -1433,14 +1433,16 @@ bool
|
|||||||
test_superuser(const char *username)
|
test_superuser(const char *username)
|
||||||
{
|
{
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
char buf[64 + NAMEDATALEN];
|
PQExpBufferData buf;
|
||||||
bool answer;
|
bool answer;
|
||||||
|
|
||||||
if (!username)
|
if (!username)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
sprintf(buf, "SELECT usesuper FROM pg_user WHERE usename = '%.*s'", NAMEDATALEN, username);
|
initPQExpBuffer(&buf);
|
||||||
res = PSQLexec(buf);
|
printfPQExpBuffer(&buf, "SELECT usesuper FROM pg_user WHERE usename = '%s'", username);
|
||||||
|
res = PSQLexec(buf.data);
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
|
|
||||||
answer =
|
answer =
|
||||||
(PQntuples(res) > 0 && PQnfields(res) > 0
|
(PQntuples(res) > 0 && PQnfields(res) > 0
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright 2000 by PostgreSQL Global Development Group
|
* Copyright 2000 by PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.20 2002/02/23 21:46:03 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.21 2002/04/24 05:24:00 petere Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
@ -19,6 +19,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "libpq-fe.h"
|
#include "libpq-fe.h"
|
||||||
|
#include "pqexpbuffer.h"
|
||||||
#include "pqsignal.h"
|
#include "pqsignal.h"
|
||||||
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
@ -229,12 +230,12 @@ parse_slash_copy(const char *args)
|
|||||||
bool
|
bool
|
||||||
do_copy(const char *args)
|
do_copy(const char *args)
|
||||||
{
|
{
|
||||||
char query[128 + NAMEDATALEN];
|
PQExpBufferData query;
|
||||||
FILE *copystream;
|
FILE *copystream;
|
||||||
struct copy_options *options;
|
struct copy_options *options;
|
||||||
PGresult *result;
|
PGresult *result;
|
||||||
bool success;
|
bool success;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
/* parse options */
|
/* parse options */
|
||||||
options = parse_slash_copy(args);
|
options = parse_slash_copy(args);
|
||||||
@ -242,35 +243,27 @@ do_copy(const char *args)
|
|||||||
if (!options)
|
if (!options)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
strcpy(query, "COPY ");
|
initPQExpBuffer(&query);
|
||||||
if (options->binary)
|
|
||||||
strcat(query, "BINARY ");
|
|
||||||
|
|
||||||
strcat(query, "\"");
|
printfPQExpBuffer(&query, "COPY ");
|
||||||
strncat(query, options->table, NAMEDATALEN);
|
if (options->binary)
|
||||||
strcat(query, "\" ");
|
appendPQExpBuffer(&query, "BINARY ");
|
||||||
|
|
||||||
|
appendPQExpBuffer(&query, "\"%s\" ", options->table);
|
||||||
if (options->oids)
|
if (options->oids)
|
||||||
strcat(query, "WITH OIDS ");
|
appendPQExpBuffer(&query, "WITH OIDS ");
|
||||||
|
|
||||||
if (options->from)
|
if (options->from)
|
||||||
strcat(query, "FROM STDIN");
|
appendPQExpBuffer(&query, "FROM STDIN");
|
||||||
else
|
else
|
||||||
strcat(query, "TO STDOUT");
|
appendPQExpBuffer(&query, "TO STDOUT");
|
||||||
|
|
||||||
|
|
||||||
if (options->delim)
|
if (options->delim)
|
||||||
{
|
appendPQExpBuffer(&query, " USING DELIMITERS '%s'", options->delim);
|
||||||
strcat(query, " USING DELIMITERS '");
|
|
||||||
strcat(query, options->delim);
|
|
||||||
strcat(query, "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options->null)
|
if (options->null)
|
||||||
{
|
appendPQExpBuffer(&query, " WITH NULL AS '%s'", options->null);
|
||||||
strcat(query, " WITH NULL AS '");
|
|
||||||
strcat(query, options->null);
|
|
||||||
strcat(query, "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options->from)
|
if (options->from)
|
||||||
{
|
{
|
||||||
@ -294,17 +287,20 @@ do_copy(const char *args)
|
|||||||
free_copy_options(options);
|
free_copy_options(options);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* make sure the specified file is not a directory */
|
|
||||||
fstat(fileno(copystream),&st);
|
/* make sure the specified file is not a directory */
|
||||||
if( S_ISDIR(st.st_mode) ){
|
fstat(fileno(copystream), &st);
|
||||||
fclose(copystream);
|
if( S_ISDIR(st.st_mode) )
|
||||||
|
{
|
||||||
|
fclose(copystream);
|
||||||
psql_error("%s: cannot COPY TO/FROM a directory\n",
|
psql_error("%s: cannot COPY TO/FROM a directory\n",
|
||||||
options->file);
|
options->file);
|
||||||
free_copy_options(options);
|
free_copy_options(options);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = PSQLexec(query);
|
result = PSQLexec(query.data);
|
||||||
|
termPQExpBuffer(&query);
|
||||||
|
|
||||||
switch (PQresultStatus(result))
|
switch (PQresultStatus(result))
|
||||||
{
|
{
|
||||||
|
@ -3,12 +3,13 @@
|
|||||||
*
|
*
|
||||||
* Copyright 2000 by PostgreSQL Global Development Group
|
* Copyright 2000 by PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.50 2002/04/19 23:13:54 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.51 2002/04/24 05:24:00 petere Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "describe.h"
|
#include "describe.h"
|
||||||
|
|
||||||
#include "libpq-fe.h"
|
#include "libpq-fe.h"
|
||||||
|
#include "pqexpbuffer.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
@ -26,10 +27,6 @@
|
|||||||
*----------------
|
*----------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* the maximal size of regular expression we'll accept here */
|
|
||||||
/* (it is safe to just change this here) */
|
|
||||||
#define REGEXP_CUTOFF (10 * NAMEDATALEN)
|
|
||||||
|
|
||||||
|
|
||||||
/* \da
|
/* \da
|
||||||
* takes an optional regexp to match specific aggregates by name
|
* takes an optional regexp to match specific aggregates by name
|
||||||
@ -37,15 +34,17 @@
|
|||||||
bool
|
bool
|
||||||
describeAggregates(const char *name)
|
describeAggregates(const char *name)
|
||||||
{
|
{
|
||||||
char buf[384 + REGEXP_CUTOFF];
|
PQExpBufferData buf;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
printQueryOpt myopt = pset.popt;
|
printQueryOpt myopt = pset.popt;
|
||||||
|
|
||||||
|
initPQExpBuffer(&buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are two kinds of aggregates: ones that work on particular
|
* There are two kinds of aggregates: ones that work on particular
|
||||||
* types and ones that work on all (denoted by input type = 0)
|
* types and ones that work on all (denoted by input type = 0)
|
||||||
*/
|
*/
|
||||||
snprintf(buf, sizeof(buf),
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT p.proname AS \"%s\",\n"
|
"SELECT p.proname AS \"%s\",\n"
|
||||||
" CASE p.proargtypes[0]\n"
|
" CASE p.proargtypes[0]\n"
|
||||||
" WHEN 0 THEN CAST('%s' AS text)\n"
|
" WHEN 0 THEN CAST('%s' AS text)\n"
|
||||||
@ -58,15 +57,12 @@ describeAggregates(const char *name)
|
|||||||
_("Data type"), _("Description"));
|
_("Data type"), _("Description"));
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
{
|
appendPQExpBuffer(&buf, " AND p.proname ~ '^%s'\n", name);
|
||||||
strcat(buf, " AND p.proname ~ '^");
|
|
||||||
strncat(buf, name, REGEXP_CUTOFF);
|
|
||||||
strcat(buf, "'\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
strcat(buf, "ORDER BY 1, 2;");
|
appendPQExpBuffer(&buf, "ORDER BY 1, 2;");
|
||||||
|
|
||||||
res = PSQLexec(buf);
|
res = PSQLexec(buf.data);
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -86,15 +82,17 @@ describeAggregates(const char *name)
|
|||||||
bool
|
bool
|
||||||
describeFunctions(const char *name, bool verbose)
|
describeFunctions(const char *name, bool verbose)
|
||||||
{
|
{
|
||||||
char buf[384 + REGEXP_CUTOFF];
|
PQExpBufferData buf;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
printQueryOpt myopt = pset.popt;
|
printQueryOpt myopt = pset.popt;
|
||||||
|
|
||||||
|
initPQExpBuffer(&buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we skip in/out funcs by excluding functions that take some
|
* we skip in/out funcs by excluding functions that take some
|
||||||
* arguments, but have no types defined for those arguments
|
* arguments, but have no types defined for those arguments
|
||||||
*/
|
*/
|
||||||
snprintf(buf, sizeof(buf),
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT format_type(p.prorettype, NULL) as \"%s\",\n"
|
"SELECT format_type(p.prorettype, NULL) as \"%s\",\n"
|
||||||
" p.proname as \"%s\",\n"
|
" p.proname as \"%s\",\n"
|
||||||
" oidvectortypes(p.proargtypes) as \"%s\"",
|
" oidvectortypes(p.proargtypes) as \"%s\"",
|
||||||
@ -102,7 +100,7 @@ describeFunctions(const char *name, bool verbose)
|
|||||||
_("Argument data types"));
|
_("Argument data types"));
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
appendPQExpBuffer(&buf,
|
||||||
",\n u.usename as \"%s\",\n"
|
",\n u.usename as \"%s\",\n"
|
||||||
" l.lanname as \"%s\",\n"
|
" l.lanname as \"%s\",\n"
|
||||||
" p.prosrc as \"%s\",\n"
|
" p.prosrc as \"%s\",\n"
|
||||||
@ -111,24 +109,21 @@ describeFunctions(const char *name, bool verbose)
|
|||||||
_("Source code"), _("Description"));
|
_("Source code"), _("Description"));
|
||||||
|
|
||||||
if (!verbose)
|
if (!verbose)
|
||||||
strcat(buf,
|
appendPQExpBuffer(&buf,
|
||||||
"\nFROM pg_proc p\n"
|
"\nFROM pg_proc p\n"
|
||||||
"WHERE p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg\n");
|
"WHERE p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg\n");
|
||||||
else
|
else
|
||||||
strcat(buf,
|
appendPQExpBuffer(&buf,
|
||||||
"\nFROM pg_proc p, pg_language l, pg_user u\n"
|
"\nFROM pg_proc p, pg_language l, pg_user u\n"
|
||||||
"WHERE p.prolang = l.oid AND p.proowner = u.usesysid\n"
|
"WHERE p.prolang = l.oid AND p.proowner = u.usesysid\n"
|
||||||
" AND p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg\n");
|
" AND p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg\n");
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
{
|
appendPQExpBuffer(&buf, " AND p.proname ~ '^%s'\n", name);
|
||||||
strcat(buf, " AND p.proname ~ '^");
|
appendPQExpBuffer(&buf, "ORDER BY 2, 1, 3;");
|
||||||
strncat(buf, name, REGEXP_CUTOFF);
|
|
||||||
strcat(buf, "'\n");
|
|
||||||
}
|
|
||||||
strcat(buf, "ORDER BY 2, 1, 3;");
|
|
||||||
|
|
||||||
res = PSQLexec(buf);
|
res = PSQLexec(buf.data);
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -150,22 +145,24 @@ describeFunctions(const char *name, bool verbose)
|
|||||||
bool
|
bool
|
||||||
describeTypes(const char *name, bool verbose)
|
describeTypes(const char *name, bool verbose)
|
||||||
{
|
{
|
||||||
char buf[384 + 2 * REGEXP_CUTOFF];
|
PQExpBufferData buf;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
printQueryOpt myopt = pset.popt;
|
printQueryOpt myopt = pset.popt;
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
initPQExpBuffer(&buf);
|
||||||
|
|
||||||
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT format_type(t.oid, NULL) AS \"%s\",\n",
|
"SELECT format_type(t.oid, NULL) AS \"%s\",\n",
|
||||||
_("Name"));
|
_("Name"));
|
||||||
if (verbose)
|
if (verbose)
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
appendPQExpBuffer(&buf,
|
||||||
" t.typname AS \"%s\",\n"
|
" t.typname AS \"%s\",\n"
|
||||||
" CASE WHEN t.typlen = -1\n"
|
" CASE WHEN t.typlen = -1\n"
|
||||||
" THEN CAST('var' AS text)\n"
|
" THEN CAST('var' AS text)\n"
|
||||||
" ELSE CAST(t.typlen AS text)\n"
|
" ELSE CAST(t.typlen AS text)\n"
|
||||||
" END AS \"%s\",\n",
|
" END AS \"%s\",\n",
|
||||||
_("Internal name"), _("Size"));
|
_("Internal name"), _("Size"));
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
appendPQExpBuffer(&buf,
|
||||||
" obj_description(t.oid, 'pg_type') as \"%s\"\n",
|
" obj_description(t.oid, 'pg_type') as \"%s\"\n",
|
||||||
_("Description"));
|
_("Description"));
|
||||||
|
|
||||||
@ -173,20 +170,16 @@ describeTypes(const char *name, bool verbose)
|
|||||||
* do not include array types (start with underscore), do not include
|
* do not include array types (start with underscore), do not include
|
||||||
* user relations (typrelid!=0)
|
* user relations (typrelid!=0)
|
||||||
*/
|
*/
|
||||||
strcat(buf, "FROM pg_type t\nWHERE t.typrelid = 0 AND t.typname !~ '^_.*'\n");
|
appendPQExpBuffer(&buf, "FROM pg_type t\nWHERE t.typrelid = 0 AND t.typname !~ '^_.*'\n");
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
{
|
|
||||||
/* accept either internal or external type name */
|
/* accept either internal or external type name */
|
||||||
strcat(buf, " AND (format_type(t.oid, NULL) ~ '^");
|
appendPQExpBuffer(&buf, " AND (format_type(t.oid, NULL) ~ '^%s' OR t.typname ~ '^%s')\n", name, name);
|
||||||
strncat(buf, name, REGEXP_CUTOFF);
|
|
||||||
strcat(buf, "' OR t.typname ~ '^");
|
|
||||||
strncat(buf, name, REGEXP_CUTOFF);
|
|
||||||
strcat(buf, "')\n");
|
|
||||||
}
|
|
||||||
strcat(buf, "ORDER BY 1;");
|
|
||||||
|
|
||||||
res = PSQLexec(buf);
|
appendPQExpBuffer(&buf, "ORDER BY 1;");
|
||||||
|
|
||||||
|
res = PSQLexec(buf.data);
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -206,11 +199,13 @@ describeTypes(const char *name, bool verbose)
|
|||||||
bool
|
bool
|
||||||
describeOperators(const char *name)
|
describeOperators(const char *name)
|
||||||
{
|
{
|
||||||
char buf[384 + REGEXP_CUTOFF];
|
PQExpBufferData buf;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
printQueryOpt myopt = pset.popt;
|
printQueryOpt myopt = pset.popt;
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
initPQExpBuffer(&buf);
|
||||||
|
|
||||||
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT o.oprname AS \"%s\",\n"
|
"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='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"
|
" CASE WHEN o.oprkind='r' THEN NULL ELSE format_type(o.oprright, NULL) END AS \"%s\",\n"
|
||||||
@ -220,15 +215,12 @@ describeOperators(const char *name)
|
|||||||
_("Name"), _("Left arg type"), _("Right arg type"),
|
_("Name"), _("Left arg type"), _("Right arg type"),
|
||||||
_("Result type"), _("Description"));
|
_("Result type"), _("Description"));
|
||||||
if (name)
|
if (name)
|
||||||
{
|
appendPQExpBuffer(&buf, "WHERE o.oprname = '%s'\n", name);
|
||||||
strcat(buf, "WHERE o.oprname = '");
|
|
||||||
strncat(buf, name, REGEXP_CUTOFF);
|
|
||||||
strcat(buf, "'\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
strcat(buf, "ORDER BY 1, 2, 3, 4;");
|
appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3, 4;");
|
||||||
|
|
||||||
res = PSQLexec(buf);
|
res = PSQLexec(buf.data);
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -251,27 +243,30 @@ bool
|
|||||||
listAllDbs(bool desc)
|
listAllDbs(bool desc)
|
||||||
{
|
{
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
char buf[1024];
|
PQExpBufferData buf;
|
||||||
printQueryOpt myopt = pset.popt;
|
printQueryOpt myopt = pset.popt;
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
initPQExpBuffer(&buf);
|
||||||
|
|
||||||
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT d.datname as \"%s\",\n"
|
"SELECT d.datname as \"%s\",\n"
|
||||||
" u.usename as \"%s\"",
|
" u.usename as \"%s\"",
|
||||||
_("Name"), _("Owner"));
|
_("Name"), _("Owner"));
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
appendPQExpBuffer(&buf,
|
||||||
",\n pg_encoding_to_char(d.encoding) as \"%s\"",
|
",\n pg_encoding_to_char(d.encoding) as \"%s\"",
|
||||||
_("Encoding"));
|
_("Encoding"));
|
||||||
#endif
|
#endif
|
||||||
if (desc)
|
if (desc)
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
appendPQExpBuffer(&buf,
|
||||||
",\n obj_description(d.oid, 'pg_database') as \"%s\"",
|
",\n obj_description(d.oid, 'pg_database') as \"%s\"",
|
||||||
_("Description"));
|
_("Description"));
|
||||||
strcat(buf,
|
appendPQExpBuffer(&buf,
|
||||||
"\nFROM pg_database d LEFT JOIN pg_user u ON d.datdba = u.usesysid\n"
|
"\nFROM pg_database d LEFT JOIN pg_user u ON d.datdba = u.usesysid\n"
|
||||||
"ORDER BY 1;");
|
"ORDER BY 1;");
|
||||||
|
|
||||||
res = PSQLexec(buf);
|
res = PSQLexec(buf.data);
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -292,12 +287,14 @@ listAllDbs(bool desc)
|
|||||||
bool
|
bool
|
||||||
permissionsList(const char *name)
|
permissionsList(const char *name)
|
||||||
{
|
{
|
||||||
char buf[256 + REGEXP_CUTOFF];
|
PQExpBufferData buf;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
printQueryOpt myopt = pset.popt;
|
printQueryOpt myopt = pset.popt;
|
||||||
|
|
||||||
|
initPQExpBuffer(&buf);
|
||||||
|
|
||||||
/* Currently, we ignore indexes since they have no meaningful rights */
|
/* Currently, we ignore indexes since they have no meaningful rights */
|
||||||
snprintf(buf, sizeof(buf),
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT relname as \"%s\",\n"
|
"SELECT relname as \"%s\",\n"
|
||||||
" relacl as \"%s\"\n"
|
" relacl as \"%s\"\n"
|
||||||
"FROM pg_class\n"
|
"FROM pg_class\n"
|
||||||
@ -305,23 +302,23 @@ permissionsList(const char *name)
|
|||||||
" relname NOT LIKE 'pg$_%%' ESCAPE '$'\n",
|
" relname NOT LIKE 'pg$_%%' ESCAPE '$'\n",
|
||||||
_("Table"), _("Access privileges"));
|
_("Table"), _("Access privileges"));
|
||||||
if (name)
|
if (name)
|
||||||
{
|
appendPQExpBuffer(&buf, " AND relname ~ '^%s'\n", name);
|
||||||
strcat(buf, " AND relname ~ '^");
|
appendPQExpBuffer(&buf, "ORDER BY 1;");
|
||||||
strncat(buf, name, REGEXP_CUTOFF);
|
|
||||||
strcat(buf, "'\n");
|
|
||||||
}
|
|
||||||
strcat(buf, "ORDER BY 1;");
|
|
||||||
|
|
||||||
res = PSQLexec(buf);
|
res = PSQLexec(buf.data);
|
||||||
if (!res)
|
if (!res)
|
||||||
|
{
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
myopt.nullPrint = NULL;
|
myopt.nullPrint = NULL;
|
||||||
sprintf(buf, _("Access privileges for database \"%s\""), PQdb(pset.db));
|
printfPQExpBuffer(&buf, _("Access privileges for database \"%s\""), PQdb(pset.db));
|
||||||
myopt.title = buf;
|
myopt.title = buf.data;
|
||||||
|
|
||||||
printQuery(res, &myopt, pset.queryFout);
|
printQuery(res, &myopt, pset.queryFout);
|
||||||
|
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -339,11 +336,13 @@ permissionsList(const char *name)
|
|||||||
bool
|
bool
|
||||||
objectDescription(const char *object)
|
objectDescription(const char *object)
|
||||||
{
|
{
|
||||||
char descbuf[2048 + REGEXP_CUTOFF];
|
PQExpBufferData buf;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
printQueryOpt myopt = pset.popt;
|
printQueryOpt myopt = pset.popt;
|
||||||
|
|
||||||
snprintf(descbuf, sizeof(descbuf),
|
initPQExpBuffer(&buf);
|
||||||
|
|
||||||
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT DISTINCT tt.name AS \"%s\", tt.object AS \"%s\", d.description AS \"%s\"\n"
|
"SELECT DISTINCT tt.name AS \"%s\", tt.object AS \"%s\", d.description AS \"%s\"\n"
|
||||||
"FROM (\n"
|
"FROM (\n"
|
||||||
|
|
||||||
@ -407,15 +406,11 @@ objectDescription(const char *object)
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (object)
|
if (object)
|
||||||
{
|
appendPQExpBuffer(&buf, " AND tt.name ~ '^%s'\n", object);
|
||||||
strcat(descbuf, " AND tt.name ~ '^");
|
appendPQExpBuffer(&buf, "ORDER BY 1;");
|
||||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
|
||||||
strcat(descbuf, "'\n");
|
|
||||||
}
|
|
||||||
strcat(descbuf, "ORDER BY 1;");
|
|
||||||
|
|
||||||
|
res = PSQLexec(buf.data);
|
||||||
res = PSQLexec(descbuf);
|
termPQExpBuffer(&buf);
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -457,17 +452,17 @@ xmalloc(size_t size)
|
|||||||
bool
|
bool
|
||||||
describeTableDetails(const char *name, bool desc)
|
describeTableDetails(const char *name, bool desc)
|
||||||
{
|
{
|
||||||
char buf[512 + INDEX_MAX_KEYS * NAMEDATALEN];
|
PQExpBufferData buf;
|
||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
printTableOpt myopt = pset.popt.topt;
|
printTableOpt myopt = pset.popt.topt;
|
||||||
int i;
|
int i;
|
||||||
const char *view_def = NULL;
|
const char *view_def = NULL;
|
||||||
const char *headers[5];
|
const char *headers[5];
|
||||||
char **cells = NULL;
|
char **cells = NULL;
|
||||||
char *title = NULL;
|
|
||||||
char **footers = NULL;
|
char **footers = NULL;
|
||||||
char **ptr;
|
char **ptr;
|
||||||
unsigned int cols;
|
PQExpBufferData title;
|
||||||
|
unsigned int cols = 0;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool hasindex;
|
bool hasindex;
|
||||||
@ -476,26 +471,21 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
int16 triggers;
|
int16 triggers;
|
||||||
bool hasrules;
|
bool hasrules;
|
||||||
} tableinfo;
|
} tableinfo;
|
||||||
bool error = false;
|
bool retval;
|
||||||
|
|
||||||
/* truncate table name */
|
retval = false;
|
||||||
if (strlen(name) > NAMEDATALEN)
|
|
||||||
{
|
|
||||||
char *my_name = xmalloc(NAMEDATALEN + 1);
|
|
||||||
|
|
||||||
strncpy(my_name, name, NAMEDATALEN);
|
initPQExpBuffer(&buf);
|
||||||
my_name[NAMEDATALEN] = '\0';
|
initPQExpBuffer(&title);
|
||||||
name = my_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get general table info */
|
/* Get general table info */
|
||||||
sprintf(buf,
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules\n"
|
"SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules\n"
|
||||||
"FROM pg_class WHERE relname='%s'",
|
"FROM pg_class WHERE relname='%s'",
|
||||||
name);
|
name);
|
||||||
res = PSQLexec(buf);
|
res = PSQLexec(buf.data);
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
goto error_return;
|
||||||
|
|
||||||
/* Did we get anything? */
|
/* Did we get anything? */
|
||||||
if (PQntuples(res) == 0)
|
if (PQntuples(res) == 0)
|
||||||
@ -503,7 +493,8 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
if (!QUIET())
|
if (!QUIET())
|
||||||
fprintf(stderr, _("Did not find any relation named \"%s\".\n"), name);
|
fprintf(stderr, _("Did not find any relation named \"%s\".\n"), name);
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
return false;
|
res = NULL;
|
||||||
|
goto error_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: check for null pointers here? */
|
/* FIXME: check for null pointers here? */
|
||||||
@ -536,38 +527,36 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
|
|
||||||
/* Get column info (index requires additional checks) */
|
/* Get column info (index requires additional checks) */
|
||||||
if (tableinfo.relkind == 'i')
|
if (tableinfo.relkind == 'i')
|
||||||
strcpy(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, ");
|
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, ");
|
||||||
else
|
else
|
||||||
strcpy(buf, "SELECT a.attname, ");
|
printfPQExpBuffer(&buf, "SELECT a.attname, ");
|
||||||
strcat(buf, "format_type(a.atttypid, a.atttypmod), a.attnotnull, a.atthasdef, a.attnum");
|
appendPQExpBuffer(&buf, "format_type(a.atttypid, a.atttypmod), a.attnotnull, a.atthasdef, a.attnum");
|
||||||
if (desc)
|
if (desc)
|
||||||
strcat(buf, ", col_description(a.attrelid, a.attnum)");
|
appendPQExpBuffer(&buf, ", col_description(a.attrelid, a.attnum)");
|
||||||
strcat(buf, "\nFROM pg_class c, pg_attribute a");
|
appendPQExpBuffer(&buf, "\nFROM pg_class c, pg_attribute a");
|
||||||
if (tableinfo.relkind == 'i')
|
if (tableinfo.relkind == 'i')
|
||||||
strcat(buf, ", pg_index i");
|
appendPQExpBuffer(&buf, ", pg_index i");
|
||||||
strcat(buf, "\nWHERE c.relname = '");
|
appendPQExpBuffer(&buf, "\nWHERE c.relname = '%s'\n AND a.attnum > 0 AND a.attrelid = c.oid", name);
|
||||||
strncat(buf, name, NAMEDATALEN);
|
|
||||||
strcat(buf, "'\n AND a.attnum > 0 AND a.attrelid = c.oid");
|
|
||||||
if (tableinfo.relkind == 'i')
|
if (tableinfo.relkind == 'i')
|
||||||
strcat(buf, " AND a.attrelid = i.indexrelid");
|
appendPQExpBuffer(&buf, " AND a.attrelid = i.indexrelid");
|
||||||
strcat(buf, "\nORDER BY a.attnum");
|
appendPQExpBuffer(&buf, "\nORDER BY a.attnum");
|
||||||
|
|
||||||
res = PSQLexec(buf);
|
res = PSQLexec(buf.data);
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
goto error_return;
|
||||||
|
|
||||||
/* Check if table is a view */
|
/* Check if table is a view */
|
||||||
if (tableinfo.hasrules)
|
if (tableinfo.hasrules)
|
||||||
{
|
{
|
||||||
PGresult *result;
|
PGresult *result;
|
||||||
|
|
||||||
sprintf(buf, "SELECT definition FROM pg_views WHERE viewname = '%s'", name);
|
printfPQExpBuffer(&buf, "SELECT definition FROM pg_views WHERE viewname = '%s'", name);
|
||||||
result = PSQLexec(buf);
|
result = PSQLexec(buf.data);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
return false;
|
goto error_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PQntuples(result) > 0)
|
if (PQntuples(result) > 0)
|
||||||
@ -603,56 +592,50 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
{
|
{
|
||||||
PGresult *result;
|
PGresult *result;
|
||||||
|
|
||||||
sprintf(buf, "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n"
|
printfPQExpBuffer(&buf,
|
||||||
"WHERE c.relname = '%s' AND c.oid = d.adrelid AND d.adnum = %s",
|
"SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n"
|
||||||
name, PQgetvalue(res, i, 4));
|
"WHERE c.relname = '%s' AND c.oid = d.adrelid AND d.adnum = %s",
|
||||||
|
name, PQgetvalue(res, i, 4));
|
||||||
|
|
||||||
result = PSQLexec(buf);
|
result = PSQLexec(buf.data);
|
||||||
if (!result)
|
|
||||||
error = true;
|
if (cells[i * cols + 2][0])
|
||||||
else
|
strcat(cells[i * cols + 2], " ");
|
||||||
{
|
strcat(cells[i * cols + 2], "default ");
|
||||||
if (cells[i * cols + 2][0])
|
strcat(cells[i * cols + 2], result ? PQgetvalue(result, 0, 0) : "?");
|
||||||
strcat(cells[i * cols + 2], " ");
|
|
||||||
strcat(cells[i * cols + 2], "default ");
|
PQclear(result);
|
||||||
strcat(cells[i * cols + 2], PQgetvalue(result, 0, 0));
|
|
||||||
PQclear(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Description */
|
/* Description */
|
||||||
if (desc)
|
if (desc)
|
||||||
cells[i * cols + cols - 1] = PQgetvalue(res, i, 5);
|
cells[i * cols + cols - 1] = PQgetvalue(res, i, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make title */
|
/* Make title */
|
||||||
title = xmalloc(32 + NAMEDATALEN);
|
|
||||||
switch (tableinfo.relkind)
|
switch (tableinfo.relkind)
|
||||||
{
|
{
|
||||||
case 'r':
|
case 'r':
|
||||||
snprintf(title, 32 + NAMEDATALEN, _("Table \"%s\""), name);
|
printfPQExpBuffer(&title, _("Table \"%s\""), name);
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
snprintf(title, 32 + NAMEDATALEN, _("View \"%s\""), name);
|
printfPQExpBuffer(&title, _("View \"%s\""), name);
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
snprintf(title, 32 + NAMEDATALEN, _("Sequence \"%s\""), name);
|
printfPQExpBuffer(&title, _("Sequence \"%s\""), name);
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
snprintf(title, 32 + NAMEDATALEN, _("Index \"%s\""), name);
|
printfPQExpBuffer(&title, _("Index \"%s\""), name);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
snprintf(title, 32 + NAMEDATALEN, _("Special relation \"%s\""), name);
|
printfPQExpBuffer(&title, _("Special relation \"%s\""), name);
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
snprintf(title, 32 + NAMEDATALEN, _("TOAST table \"%s\""), name);
|
printfPQExpBuffer(&title, _("TOAST table \"%s\""), name);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(title, 32 + NAMEDATALEN, _("?%c? \"%s\""), tableinfo.relkind, name);
|
printfPQExpBuffer(&title, _("?%c? \"%s\""), tableinfo.relkind, name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,16 +644,22 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
{
|
{
|
||||||
/* Footer information about an index */
|
/* Footer information about an index */
|
||||||
PGresult *result;
|
PGresult *result;
|
||||||
sprintf(buf, "SELECT i.indisunique, i.indisprimary, a.amname, c2.relname,\n"
|
printfPQExpBuffer(&buf,
|
||||||
"pg_get_expr(i.indpred,i.indrelid)\n"
|
"SELECT i.indisunique, i.indisprimary, a.amname, c2.relname,\n"
|
||||||
"FROM pg_index i, pg_class c, pg_class c2, pg_am a\n"
|
"pg_get_expr(i.indpred,i.indrelid)\n"
|
||||||
"WHERE i.indexrelid = c.oid AND c.relname = '%s' AND c.relam = a.oid\n"
|
"FROM pg_index i, pg_class c, pg_class c2, pg_am a\n"
|
||||||
"AND i.indrelid = c2.oid",
|
"WHERE i.indexrelid = c.oid AND c.relname = '%s' AND c.relam = a.oid\n"
|
||||||
name);
|
"AND i.indrelid = c2.oid",
|
||||||
|
name);
|
||||||
|
|
||||||
result = PSQLexec(buf);
|
result = PSQLexec(buf.data);
|
||||||
if (!result || PQntuples(result) != 1)
|
if (!result)
|
||||||
error = true;
|
goto error_return;
|
||||||
|
else if (PQntuples(result) != 1)
|
||||||
|
{
|
||||||
|
PQclear(result);
|
||||||
|
goto error_return;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *indisunique = PQgetvalue(result, 0, 0);
|
char *indisunique = PQgetvalue(result, 0, 0);
|
||||||
@ -699,17 +688,17 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
int count_footers = 0;
|
int count_footers = 0;
|
||||||
|
|
||||||
/* count rules */
|
/* count rules */
|
||||||
if (!error && tableinfo.hasrules)
|
if (tableinfo.hasrules)
|
||||||
{
|
{
|
||||||
sprintf(buf,
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT r.rulename\n"
|
"SELECT r.rulename\n"
|
||||||
"FROM pg_rewrite r, pg_class c\n"
|
"FROM pg_rewrite r, pg_class c\n"
|
||||||
"WHERE c.relname = '%s' AND c.oid = r.ev_class\n"
|
"WHERE c.relname = '%s' AND c.oid = r.ev_class\n"
|
||||||
"AND r.rulename != '_RETURN'",
|
"AND r.rulename != '_RETURN'",
|
||||||
name);
|
name);
|
||||||
result = PSQLexec(buf);
|
result = PSQLexec(buf.data);
|
||||||
if (!result)
|
if (!result)
|
||||||
error = true;
|
goto error_return;
|
||||||
else
|
else
|
||||||
rule_count = PQntuples(result);
|
rule_count = PQntuples(result);
|
||||||
}
|
}
|
||||||
@ -727,13 +716,13 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
char *s = _("Rules");
|
char *s = _("Rules");
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result, i, 0));
|
printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result, i, 0));
|
||||||
else
|
else
|
||||||
snprintf(buf, sizeof(buf), "%*s %s", (int) strlen(s), "", PQgetvalue(result, i, 0));
|
printfPQExpBuffer(&buf, "%*s %s", (int) strlen(s), "", PQgetvalue(result, i, 0));
|
||||||
if (i < rule_count - 1)
|
if (i < rule_count - 1)
|
||||||
strcat(buf, ",");
|
appendPQExpBuffer(&buf, ",");
|
||||||
|
|
||||||
footers[count_footers++] = xstrdup(buf);
|
footers[count_footers++] = xstrdup(buf.data);
|
||||||
}
|
}
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
|
|
||||||
@ -754,62 +743,64 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
int count_footers = 0;
|
int count_footers = 0;
|
||||||
|
|
||||||
/* count indexes */
|
/* count indexes */
|
||||||
if (!error && tableinfo.hasindex)
|
if (tableinfo.hasindex)
|
||||||
{
|
{
|
||||||
sprintf(buf, "SELECT c2.relname, i.indisprimary, i.indisunique,\n"
|
printfPQExpBuffer(&buf,
|
||||||
|
"SELECT c2.relname, i.indisprimary, i.indisunique,\n"
|
||||||
"SUBSTR(pg_get_indexdef(i.indexrelid),\n"
|
"SUBSTR(pg_get_indexdef(i.indexrelid),\n"
|
||||||
"POSITION('USING ' IN pg_get_indexdef(i.indexrelid))+5)\n"
|
"POSITION('USING ' IN pg_get_indexdef(i.indexrelid))+5)\n"
|
||||||
"FROM pg_class c, pg_class c2, pg_index i\n"
|
"FROM pg_class c, pg_class c2, pg_index i\n"
|
||||||
"WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
|
"WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
|
||||||
"ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname",
|
"ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname",
|
||||||
name);
|
name);
|
||||||
result1 = PSQLexec(buf);
|
result1 = PSQLexec(buf.data);
|
||||||
if (!result1)
|
if (!result1)
|
||||||
error = true;
|
goto error_return;
|
||||||
else
|
else
|
||||||
index_count = PQntuples(result1);
|
index_count = PQntuples(result1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* count table (and column) constraints */
|
/* count table (and column) constraints */
|
||||||
if (!error && tableinfo.checks)
|
if (tableinfo.checks)
|
||||||
{
|
{
|
||||||
sprintf(buf, "SELECT rcsrc, rcname\n"
|
printfPQExpBuffer(&buf,
|
||||||
|
"SELECT rcsrc, rcname\n"
|
||||||
"FROM pg_relcheck r, pg_class c\n"
|
"FROM pg_relcheck r, pg_class c\n"
|
||||||
"WHERE c.relname='%s' AND c.oid = r.rcrelid",
|
"WHERE c.relname='%s' AND c.oid = r.rcrelid",
|
||||||
name);
|
name);
|
||||||
result2 = PSQLexec(buf);
|
result2 = PSQLexec(buf.data);
|
||||||
if (!result2)
|
if (!result2)
|
||||||
error = true;
|
goto error_return;
|
||||||
else
|
else
|
||||||
constr_count = PQntuples(result2);
|
constr_count = PQntuples(result2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* count rules */
|
/* count rules */
|
||||||
if (!error && tableinfo.hasrules)
|
if (tableinfo.hasrules)
|
||||||
{
|
{
|
||||||
sprintf(buf,
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT r.rulename\n"
|
"SELECT r.rulename\n"
|
||||||
"FROM pg_rewrite r, pg_class c\n"
|
"FROM pg_rewrite r, pg_class c\n"
|
||||||
"WHERE c.relname='%s' AND c.oid = r.ev_class",
|
"WHERE c.relname='%s' AND c.oid = r.ev_class",
|
||||||
name);
|
name);
|
||||||
result3 = PSQLexec(buf);
|
result3 = PSQLexec(buf.data);
|
||||||
if (!result3)
|
if (!result3)
|
||||||
error = true;
|
goto error_return;
|
||||||
else
|
else
|
||||||
rule_count = PQntuples(result3);
|
rule_count = PQntuples(result3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* count triggers */
|
/* count triggers */
|
||||||
if (!error && tableinfo.triggers)
|
if (tableinfo.triggers)
|
||||||
{
|
{
|
||||||
sprintf(buf,
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT t.tgname\n"
|
"SELECT t.tgname\n"
|
||||||
"FROM pg_trigger t, pg_class c\n"
|
"FROM pg_trigger t, pg_class c\n"
|
||||||
"WHERE c.relname='%s' AND c.oid = t.tgrelid",
|
"WHERE c.relname='%s' AND c.oid = t.tgrelid",
|
||||||
name);
|
name);
|
||||||
result4 = PSQLexec(buf);
|
result4 = PSQLexec(buf.data);
|
||||||
if (!result4)
|
if (!result4)
|
||||||
error = true;
|
goto error_return;
|
||||||
else
|
else
|
||||||
trigger_count = PQntuples(result4);
|
trigger_count = PQntuples(result4);
|
||||||
}
|
}
|
||||||
@ -823,21 +814,25 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
char *s = _("Indexes");
|
char *s = _("Indexes");
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result1, i, 0));
|
printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result1, i, 0));
|
||||||
else
|
else
|
||||||
snprintf(buf, sizeof(buf), "%*s %s", (int) strlen(s), "", PQgetvalue(result1, i, 0));
|
printfPQExpBuffer(&buf, "%*s %s", (int) strlen(s), "", PQgetvalue(result1, i, 0));
|
||||||
|
|
||||||
/* Label as primary key or unique (but not both) */
|
/* Label as primary key or unique (but not both) */
|
||||||
strcat(buf, strcmp(PQgetvalue(result1,i,1),"t") == 0 ?
|
appendPQExpBuffer(&buf,
|
||||||
_(" primary key") : strcmp(PQgetvalue(result1,i,2),"t") == 0 ? _(" unique") : "");
|
strcmp(PQgetvalue(result1,i,1),"t") == 0
|
||||||
|
? _(" primary key") :
|
||||||
|
(strcmp(PQgetvalue(result1,i,2),"t") == 0
|
||||||
|
? _(" unique")
|
||||||
|
: ""));
|
||||||
|
|
||||||
/* Everything after "USING" is echoed verbatim */
|
/* Everything after "USING" is echoed verbatim */
|
||||||
strcat(buf, PQgetvalue(result1,i,3));
|
appendPQExpBuffer(&buf, "%s", PQgetvalue(result1,i,3));
|
||||||
|
|
||||||
if (i < index_count - 1)
|
if (i < index_count - 1)
|
||||||
strcat(buf, ",");
|
appendPQExpBuffer(&buf, ",");
|
||||||
|
|
||||||
footers[count_footers++] = xstrdup(buf);
|
footers[count_footers++] = xstrdup(buf.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -847,12 +842,16 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
char *s = _("Check constraints");
|
char *s = _("Check constraints");
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
snprintf(buf, sizeof(buf), _("%s: \"%s\" %s"), s,
|
printfPQExpBuffer(&buf, _("%s: \"%s\" %s"),
|
||||||
PQgetvalue(result2, i, 1), PQgetvalue(result2, i, 0));
|
s,
|
||||||
|
PQgetvalue(result2, i, 1),
|
||||||
|
PQgetvalue(result2, i, 0));
|
||||||
else
|
else
|
||||||
snprintf(buf, sizeof(buf), _("%*s \"%s\" %s"), (int) strlen(s), "",
|
printfPQExpBuffer(&buf, _("%*s \"%s\" %s"),
|
||||||
PQgetvalue(result2, i, 1), PQgetvalue(result2, i, 0));
|
(int) strlen(s), "",
|
||||||
footers[count_footers++] = xstrdup(buf);
|
PQgetvalue(result2, i, 1),
|
||||||
|
PQgetvalue(result2, i, 0));
|
||||||
|
footers[count_footers++] = xstrdup(buf.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* print rules */
|
/* print rules */
|
||||||
@ -861,13 +860,13 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
char *s = _("Rules");
|
char *s = _("Rules");
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result3, i, 0));
|
printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result3, i, 0));
|
||||||
else
|
else
|
||||||
snprintf(buf, sizeof(buf), "%*s %s", (int) strlen(s), "", PQgetvalue(result3, i, 0));
|
printfPQExpBuffer(&buf, "%*s %s", (int) strlen(s), "", PQgetvalue(result3, i, 0));
|
||||||
if (i < rule_count - 1)
|
if (i < rule_count - 1)
|
||||||
strcat(buf, ",");
|
appendPQExpBuffer(&buf, ",");
|
||||||
|
|
||||||
footers[count_footers++] = xstrdup(buf);
|
footers[count_footers++] = xstrdup(buf.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* print triggers */
|
/* print triggers */
|
||||||
@ -876,13 +875,13 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
char *s = _("Triggers");
|
char *s = _("Triggers");
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result4, i, 0));
|
printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result4, i, 0));
|
||||||
else
|
else
|
||||||
snprintf(buf, sizeof(buf), "%*s %s", (int) strlen(s), "", PQgetvalue(result4, i, 0));
|
printfPQExpBuffer(&buf, "%*s %s", (int) strlen(s), "", PQgetvalue(result4, i, 0));
|
||||||
if (i < trigger_count - 1)
|
if (i < trigger_count - 1)
|
||||||
strcat(buf, ",");
|
appendPQExpBuffer(&buf, ",");
|
||||||
|
|
||||||
footers[count_footers++] = xstrdup(buf);
|
footers[count_footers++] = xstrdup(buf.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end of list marker */
|
/* end of list marker */
|
||||||
@ -894,28 +893,37 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
PQclear(result4);
|
PQclear(result4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error)
|
printTable(title.data, headers,
|
||||||
printTable(title, headers,
|
(const char **) cells, (const char **) footers,
|
||||||
(const char **) cells, (const char **) footers,
|
"llll", &myopt, pset.queryFout);
|
||||||
"llll", &myopt, pset.queryFout);
|
|
||||||
|
retval = true;
|
||||||
|
|
||||||
|
error_return:
|
||||||
|
|
||||||
/* clean up */
|
/* clean up */
|
||||||
free(title);
|
termPQExpBuffer(&buf);
|
||||||
|
termPQExpBuffer(&title);
|
||||||
|
|
||||||
for (i = 0; i < PQntuples(res); i++)
|
if (cells)
|
||||||
{
|
{
|
||||||
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')
|
for (i = 0; i < PQntuples(res); i++)
|
||||||
free(cells[i * cols + 2]);
|
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')
|
||||||
|
free(cells[i * cols + 2]);
|
||||||
|
free(cells);
|
||||||
}
|
}
|
||||||
free(cells);
|
|
||||||
|
|
||||||
for (ptr = footers; footers && *ptr; ptr++)
|
if (footers)
|
||||||
free(*ptr);
|
{
|
||||||
free(footers);
|
for (ptr = footers; *ptr; ptr++)
|
||||||
|
free(*ptr);
|
||||||
|
free(footers);
|
||||||
|
}
|
||||||
|
|
||||||
PQclear(res);
|
if (res)
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
return !error;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -925,18 +933,19 @@ describeTableDetails(const char *name, bool desc)
|
|||||||
* Describes users, possibly based on a simplistic prefix search on the
|
* Describes users, possibly based on a simplistic prefix search on the
|
||||||
* argument.
|
* argument.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
describeUsers(const char *name)
|
describeUsers(const char *name)
|
||||||
{
|
{
|
||||||
char buf[384 + REGEXP_CUTOFF];
|
PQExpBufferData buf;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
printQueryOpt myopt = pset.popt;
|
printQueryOpt myopt = pset.popt;
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
initPQExpBuffer(&buf);
|
||||||
|
|
||||||
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT u.usename AS \"%s\",\n"
|
"SELECT u.usename AS \"%s\",\n"
|
||||||
" u.usesysid AS \"%s\",\n"
|
" u.usesysid AS \"%s\",\n"
|
||||||
" CASE WHEN u.usesuper AND u.usecreatedb THEN CAST('%s' AS text)\n"
|
" CASE WHEN u.usesuper AND u.usecreatedb THEN CAST('%s' AS text)\n"
|
||||||
" WHEN u.usesuper THEN CAST('%s' AS text)\n"
|
" WHEN u.usesuper THEN CAST('%s' AS text)\n"
|
||||||
" WHEN u.usecreatedb THEN CAST('%s' AS text)\n"
|
" WHEN u.usecreatedb THEN CAST('%s' AS text)\n"
|
||||||
" ELSE CAST('' AS text)\n"
|
" ELSE CAST('' AS text)\n"
|
||||||
@ -947,14 +956,11 @@ describeUsers(const char *name)
|
|||||||
_("superuser"), _("create database"),
|
_("superuser"), _("create database"),
|
||||||
_("Attributes"));
|
_("Attributes"));
|
||||||
if (name)
|
if (name)
|
||||||
{
|
appendPQExpBuffer(&buf, "WHERE u.usename ~ '^%s'\n", name);
|
||||||
strcat(buf, "WHERE u.usename ~ '^");
|
appendPQExpBuffer(&buf, "ORDER BY 1;");
|
||||||
strncat(buf, name, REGEXP_CUTOFF);
|
|
||||||
strcat(buf, "'\n");
|
|
||||||
}
|
|
||||||
strcat(buf, "ORDER BY 1;");
|
|
||||||
|
|
||||||
res = PSQLexec(buf);
|
res = PSQLexec(buf.data);
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -994,17 +1000,16 @@ listTables(const char *infotype, const char *name, bool desc)
|
|||||||
bool showSeq = strchr(infotype, 's') != NULL;
|
bool showSeq = strchr(infotype, 's') != NULL;
|
||||||
bool showSystem = strchr(infotype, 'S') != NULL;
|
bool showSystem = strchr(infotype, 'S') != NULL;
|
||||||
|
|
||||||
char buf[3072 + 8 * REGEXP_CUTOFF];
|
PQExpBufferData buf;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
printQueryOpt myopt = pset.popt;
|
printQueryOpt myopt = pset.popt;
|
||||||
|
|
||||||
if (showSystem && !(showSeq || showIndexes || showViews || showTables))
|
if (showSystem && !(showSeq || showIndexes || showViews || showTables))
|
||||||
showTables = showViews = showSeq = true;
|
showTables = showViews = showSeq = true;
|
||||||
|
|
||||||
|
initPQExpBuffer(&buf);
|
||||||
|
|
||||||
buf[0] = '\0';
|
printfPQExpBuffer(&buf,
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
|
||||||
"SELECT c.relname as \"%s\",\n"
|
"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"
|
" 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\"",
|
" u.usename as \"%s\"",
|
||||||
@ -1012,50 +1017,47 @@ listTables(const char *infotype, const char *name, bool desc)
|
|||||||
_("special"), _("Type"), _("Owner"));
|
_("special"), _("Type"), _("Owner"));
|
||||||
|
|
||||||
if (desc)
|
if (desc)
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
appendPQExpBuffer(&buf,
|
||||||
",\n obj_description(c.oid, 'pg_class') as \"%s\"",
|
",\n obj_description(c.oid, 'pg_class') as \"%s\"",
|
||||||
_("Description"));
|
_("Description"));
|
||||||
if (showIndexes) {
|
if (showIndexes)
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
appendPQExpBuffer(&buf,
|
||||||
",\n c2.relname as \"%s\"",
|
",\n c2.relname as \"%s\""
|
||||||
_("Table"));
|
"\nFROM pg_class c, pg_class c2, pg_index i, pg_user u\n"
|
||||||
strcat(buf, "\nFROM pg_class c, pg_class c2, pg_index i, pg_user u\n"
|
"WHERE c.relowner = u.usesysid\n"
|
||||||
"WHERE c.relowner = u.usesysid\n"
|
"AND i.indrelid = c2.oid AND i.indexrelid = c.oid\n",
|
||||||
"AND i.indrelid = c2.oid AND i.indexrelid = c.oid\n");
|
_("Table"));
|
||||||
}
|
else
|
||||||
else {
|
appendPQExpBuffer(&buf,
|
||||||
strcat(buf, "\nFROM pg_class c, pg_user u\n"
|
"\nFROM pg_class c, pg_user u\n"
|
||||||
"WHERE c.relowner = u.usesysid\n");
|
"WHERE c.relowner = u.usesysid\n");
|
||||||
}
|
|
||||||
strcat(buf, "AND c.relkind IN (");
|
appendPQExpBuffer(&buf, "AND c.relkind IN (");
|
||||||
if (showTables)
|
if (showTables)
|
||||||
strcat(buf, "'r',");
|
appendPQExpBuffer(&buf, "'r',");
|
||||||
if (showViews)
|
if (showViews)
|
||||||
strcat(buf, "'v',");
|
appendPQExpBuffer(&buf, "'v',");
|
||||||
if (showIndexes)
|
if (showIndexes)
|
||||||
strcat(buf, "'i',");
|
appendPQExpBuffer(&buf, "'i',");
|
||||||
if (showSeq)
|
if (showSeq)
|
||||||
strcat(buf, "'S',");
|
appendPQExpBuffer(&buf, "'S',");
|
||||||
if (showSystem && showTables)
|
if (showSystem && showTables)
|
||||||
strcat(buf, "'s',");
|
appendPQExpBuffer(&buf, "'s',");
|
||||||
strcat(buf, "''"); /* dummy */
|
appendPQExpBuffer(&buf, "''"); /* dummy */
|
||||||
strcat(buf, ")\n");
|
appendPQExpBuffer(&buf, ")\n");
|
||||||
|
|
||||||
if (showSystem)
|
if (showSystem)
|
||||||
strcat(buf, " AND c.relname ~ '^pg_'\n");
|
appendPQExpBuffer(&buf, " AND c.relname ~ '^pg_'\n");
|
||||||
else
|
else
|
||||||
strcat(buf, " AND c.relname !~ '^pg_'\n");
|
appendPQExpBuffer(&buf, " AND c.relname !~ '^pg_'\n");
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
{
|
appendPQExpBuffer(&buf, " AND c.relname ~ '^%s'\n", name);
|
||||||
strcat(buf, " AND c.relname ~ '^");
|
|
||||||
strncat(buf, name, REGEXP_CUTOFF);
|
|
||||||
strcat(buf, "'\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
strcat(buf, "ORDER BY 1;");
|
appendPQExpBuffer(&buf, "ORDER BY 1;");
|
||||||
|
|
||||||
res = PSQLexec(buf);
|
res = PSQLexec(buf.data);
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1078,23 +1080,25 @@ listTables(const char *infotype, const char *name, bool desc)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* \dD [domain]
|
* \dD [domain]
|
||||||
*
|
*
|
||||||
* Describes domains, possibly based on a simplistic prefix search on the
|
* Describes domains, possibly based on a simplistic prefix search on the
|
||||||
* argument.
|
* argument.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
listDomains(const char *name)
|
listDomains(const char *name)
|
||||||
{
|
{
|
||||||
char buf[512 + REGEXP_CUTOFF];
|
PQExpBufferData buf;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
printQueryOpt myopt = pset.popt;
|
printQueryOpt myopt = pset.popt;
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
initPQExpBuffer(&buf);
|
||||||
|
|
||||||
|
printfPQExpBuffer(&buf,
|
||||||
"SELECT t.typname as \"%s\",\n"
|
"SELECT t.typname as \"%s\",\n"
|
||||||
" format_type( t.typbasetype, t.typtypmod) as \"%s\",\n"
|
" format_type(t.typbasetype, t.typtypmod) as \"%s\",\n"
|
||||||
" CASE WHEN t.typnotnull AND t.typdefault IS NOT NULL THEN 'not null default '||t.typdefault\n"
|
" 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 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"
|
" WHEN NOT t.typnotnull AND t.typdefault IS NOT NULL THEN 'default '||t.typdefault\n"
|
||||||
@ -1106,19 +1110,16 @@ listDomains(const char *name)
|
|||||||
_("Type"),
|
_("Type"),
|
||||||
_("Modifier"));
|
_("Modifier"));
|
||||||
if (name)
|
if (name)
|
||||||
{
|
appendPQExpBuffer(&buf, "AND t.typname ~ '^%s'\n", name);
|
||||||
strcat(buf, "AND t.typname ~ '^");
|
appendPQExpBuffer(&buf, "ORDER BY 1;");
|
||||||
strncat(buf, name, REGEXP_CUTOFF);
|
|
||||||
strcat(buf, "'\n");
|
|
||||||
}
|
|
||||||
strcat(buf, "ORDER BY 1;");
|
|
||||||
|
|
||||||
res = PSQLexec(buf);
|
res = PSQLexec(buf.data);
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myopt.nullPrint = NULL;
|
myopt.nullPrint = NULL;
|
||||||
myopt.title = _("List of database domains");
|
myopt.title = _("List of domains");
|
||||||
|
|
||||||
printQuery(res, &myopt, pset.queryFout);
|
printQuery(res, &myopt, pset.queryFout);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user