Here is a patch bringing oid2name into the 21st century.
Alvaro Herrera
This commit is contained in:
parent
a5713ec427
commit
0428840864
@ -1,126 +1,180 @@
|
|||||||
This utility allows administrators to view the file structure used by
|
This utility allows administrators to examine the file structure used by
|
||||||
PostgreSQL. Databases are placed in directories based on their OIDs in
|
PostgreSQL.
|
||||||
pg_database, and the tables in that directory are named by original
|
|
||||||
OIDs, stored in pg_class.relfilenode. Oid2name connects to the database
|
|
||||||
and extracts the OID and table name information.
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
Databases are placed in directories named after their OIDs in pg_database,
|
||||||
|
and the table files within a database's directory are named by "filenode"
|
||||||
|
numbers, which are stored in pg_class.relfilenode.
|
||||||
|
|
||||||
It can be used in four ways:
|
Note that while a table's filenode often matches its OID, this is *not*
|
||||||
|
necessarily the case; some operations, like TRUNCATE, REINDEX, CLUSTER
|
||||||
|
and some forms of ALTER TABLE, can change the filenode while preserving
|
||||||
|
the OID. Avoid assuming that filenode and table OID are the same.
|
||||||
|
|
||||||
|
When a table exceeds 1Gb, it is divided into gigabyte-sized "segments".
|
||||||
|
The first segment's file name is the same as the filenode; subsequent
|
||||||
|
segments are named filenode.1, filenode.2, etc.
|
||||||
|
|
||||||
oid2name
|
Tablespaces make the scenario more complicated. Each non-default
|
||||||
|
tablespace has a symlink inside the pg_tblspc directory, which points to
|
||||||
|
the physical tablespace directory (as specified in its CREATE TABLESPACE
|
||||||
|
command). The symlink is named after the tablespace's OID. Inside the
|
||||||
|
physical tablespace directory there is another directory for each database
|
||||||
|
that has elements in the tablespace, named after the database's OID.
|
||||||
|
Tables within that directory follow the filenode naming scheme. The
|
||||||
|
"pg_default" tablespace is not addressed via pg_tblspc, but corresponds to
|
||||||
|
$PGDATA/base.
|
||||||
|
|
||||||
This will connect to the template1 database and display all databases
|
Oid2name connects to the database and extracts OID, filenode, and table
|
||||||
in the system:
|
name information. You can also have it show database OIDs and tablespace
|
||||||
|
OIDs.
|
||||||
|
|
||||||
$ oid2name
|
When displaying specific tables, you can select which tables to show by
|
||||||
All databases:
|
using -o, -f and -t. The first switch takes an OID, the second takes
|
||||||
---------------------------------
|
a filenode, and the third takes a tablename (actually, it's a LIKE
|
||||||
18720 = test1
|
pattern, so you can use things like "foo%"). Note that you can use as many
|
||||||
1 = template1
|
of these switches as you like, and the listing will include all objects
|
||||||
18719 = template0
|
matched by any of the switches. Also note that these switches can only
|
||||||
18721 = test
|
show objects in the database given in -d.
|
||||||
18735 = postgres
|
|
||||||
18736 = cssi
|
|
||||||
|
|
||||||
|
If you don't give any of -o, -f or -t it will dump all the tables in the
|
||||||
|
database given in -d. If you don't give -d, it will show a database
|
||||||
|
listing. Alternatively you can give -s to get a tablespace listing.
|
||||||
|
|
||||||
oid2name -d test [-x]
|
Additional switches:
|
||||||
|
-i include indexes and sequences in the database listing.
|
||||||
This connects to the database test and shows all tables and their OIDs:
|
-x display more information about each object shown:
|
||||||
|
tablespace name, schema name, OID.
|
||||||
$ oid2name -d test
|
-S also show system objects
|
||||||
All tables from database "test":
|
(those in information_schema, pg_toast and pg_catalog schemas)
|
||||||
---------------------------------
|
-q don't display headers
|
||||||
18766 = dns
|
(useful for scripting)
|
||||||
18737 = ips
|
|
||||||
18722 = testdate
|
|
||||||
|
|
||||||
|
|
||||||
oid2name -d test -o 18737
|
|
||||||
oid2name -d test -t testdate
|
|
||||||
|
|
||||||
This will connect to the database test and display the table name for oid
|
|
||||||
18737 and the oid for table name testdate respectively:
|
|
||||||
|
|
||||||
$ oid2name -d test -o 18737
|
|
||||||
Tablename of oid 18737 from database "test":
|
|
||||||
---------------------------------
|
|
||||||
18737 = ips
|
|
||||||
|
|
||||||
|
|
||||||
$ oid2name -d test -t testdate
|
|
||||||
Oid of table testdate from database "test":
|
|
||||||
---------------------------------
|
|
||||||
18722 = testdate
|
|
||||||
|
|
||||||
Keep in mind tables over one gigabyte will be split into separate files
|
|
||||||
with numeric file extensions.
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
Sample session:
|
Sample session:
|
||||||
|
|
||||||
$ cd /u/pg/data/base
|
|
||||||
$ oid2name
|
$ oid2name
|
||||||
All databases:
|
All databases:
|
||||||
---------------------------------
|
Oid Database Name Tablespace
|
||||||
16817 = test2
|
----------------------------------
|
||||||
16578 = x
|
17228 alvherre pg_default
|
||||||
16756 = test
|
17255 regression pg_default
|
||||||
1 = template1
|
17227 template0 pg_default
|
||||||
16569 = template0
|
1 template1 pg_default
|
||||||
16818 = test3
|
|
||||||
16811 = floattest
|
|
||||||
|
|
||||||
$ cd 16756
|
$ oid2name -s
|
||||||
$ ls 1873*
|
All tablespaces:
|
||||||
18730 18731 18732 18735 18736 18737 18738 18739
|
Oid Tablespace Name
|
||||||
|
-------------------------
|
||||||
|
1663 pg_default
|
||||||
|
1664 pg_global
|
||||||
|
155151 fastdisk
|
||||||
|
155152 bigdisk
|
||||||
|
|
||||||
$ oid2name -d test -o 18737
|
$ cd $PGDATA/17228
|
||||||
Tablename of oid 18737 from database "test":
|
|
||||||
---------------------------------
|
|
||||||
18737 = ips
|
|
||||||
|
|
||||||
$ oid2name -d test -t ips
|
$ # get top 10 db objects in the default tablespace, ordered by size
|
||||||
Oid of table ips from database "test":
|
$ ls -lS * | head -10
|
||||||
---------------------------------
|
-rw------- 1 alvherre alvherre 136536064 sep 14 09:51 155173
|
||||||
18737 = ips
|
-rw------- 1 alvherre alvherre 17965056 sep 14 09:51 1155291
|
||||||
|
-rw------- 1 alvherre alvherre 1204224 sep 14 09:51 16717
|
||||||
|
-rw------- 1 alvherre alvherre 581632 sep 6 17:51 1255
|
||||||
|
-rw------- 1 alvherre alvherre 237568 sep 14 09:50 16674
|
||||||
|
-rw------- 1 alvherre alvherre 212992 sep 14 09:51 1249
|
||||||
|
-rw------- 1 alvherre alvherre 204800 sep 14 09:51 16684
|
||||||
|
-rw------- 1 alvherre alvherre 196608 sep 14 09:50 16700
|
||||||
|
-rw------- 1 alvherre alvherre 163840 sep 14 09:50 16699
|
||||||
|
-rw------- 1 alvherre alvherre 122880 sep 6 17:51 16751
|
||||||
|
|
||||||
|
$ oid2name -d alvherre -f 155173
|
||||||
|
From database "alvherre":
|
||||||
|
Filenode Table Name
|
||||||
|
----------------------
|
||||||
|
155173 accounts
|
||||||
|
|
||||||
|
$ # you can ask for more than one object
|
||||||
|
$ oid2name -d alvherre -f 155173 -f 1155291
|
||||||
|
From database "alvherre":
|
||||||
|
Filenode Table Name
|
||||||
|
-------------------------
|
||||||
|
155173 accounts
|
||||||
|
1155291 accounts_pkey
|
||||||
|
|
||||||
|
$ # you can also mix the options, and have more details
|
||||||
|
$ oid2name -d alvherre -t accounts -f 1155291 -x
|
||||||
|
From database "alvherre":
|
||||||
|
Filenode Table Name Oid Schema Tablespace
|
||||||
|
------------------------------------------------------
|
||||||
|
155173 accounts 155173 public pg_default
|
||||||
|
1155291 accounts_pkey 1155291 public pg_default
|
||||||
|
|
||||||
$ # show disk space for every db object
|
$ # show disk space for every db object
|
||||||
$ du * | while read SIZE OID
|
$ du [0-9]* |
|
||||||
|
> while read SIZE FILENODE
|
||||||
> do
|
> do
|
||||||
> echo "$SIZE `oid2name -q -d test -o $OID`"
|
> echo "$SIZE `oid2name -q -d alvherre -i -f $FILENODE`"
|
||||||
> done
|
> done
|
||||||
24 18737 = ips
|
16 1155287 branches_pkey
|
||||||
36 18722 = cities
|
16 1155289 tellers_pkey
|
||||||
|
17561 1155291 accounts_pkey
|
||||||
...
|
...
|
||||||
|
|
||||||
$ # same as above, but sort by largest first
|
$ # same, but sort by size
|
||||||
$ du * | while read SIZE OID
|
$ du [0-9]* | sort -rn | while read SIZE FN
|
||||||
> do
|
> do
|
||||||
> echo "$SIZE `oid2name -q -d test -o $OID`"
|
> echo "$SIZE `oid2name -q -d alvherre -f $FN`"
|
||||||
> done |
|
> done
|
||||||
> sort -rn
|
133466 155173 accounts
|
||||||
2048 19324 = bigtable
|
17561 1155291 accounts_pkey
|
||||||
1950 23903 = customers
|
1177 16717 pg_proc_proname_args_nsp_index
|
||||||
...
|
...
|
||||||
|
|
||||||
$ # show disk usage per database
|
$ # If you want to see what's in tablespaces, use the pg_tblspc directory
|
||||||
$ cd /u/pg/data/base
|
$ cd $PGDATA/pg_tblspc
|
||||||
$ du -s * |
|
$ oid2name -s
|
||||||
> while read SIZE OID
|
All tablespaces:
|
||||||
> do
|
Oid Tablespace Name
|
||||||
> echo "$SIZE `aspg oid2name -q | grep ^$OID' '`"
|
-------------------------
|
||||||
> done |
|
1663 pg_default
|
||||||
> sort -rn
|
1664 pg_global
|
||||||
2256 18721 = test
|
155151 fastdisk
|
||||||
2135 18735 = postgres
|
155152 bigdisk
|
||||||
..
|
|
||||||
|
|
||||||
This can be done in psql with:
|
$ # what databases have objects in tablespace "fastdisk"?
|
||||||
|
$ ls -d 155151/*
|
||||||
|
155151/17228/ 155151/PG_VERSION
|
||||||
|
|
||||||
test=> SELECT relpages, relfilenode, relname FROM pg_class ORDER BY relpages DESC;
|
$ # Oh, what was database 17228 again?
|
||||||
|
$ oid2name
|
||||||
|
All databases:
|
||||||
|
Oid Database Name Tablespace
|
||||||
|
----------------------------------
|
||||||
|
17228 alvherre pg_default
|
||||||
|
17255 regression pg_default
|
||||||
|
17227 template0 pg_default
|
||||||
|
1 template1 pg_default
|
||||||
|
|
||||||
|
$ # Let's see what objects does this database have in the tablespace.
|
||||||
|
$ cd 155151/17228
|
||||||
|
$ ls -l
|
||||||
|
total 0
|
||||||
|
-rw------- 1 postgres postgres 0 sep 13 23:20 155156
|
||||||
|
|
||||||
|
$ # OK, this is a pretty small table ... but which one is it?
|
||||||
|
$ oid2name -d alvherre -f 155156
|
||||||
|
From database "alvherre":
|
||||||
|
Filenode Table Name
|
||||||
|
----------------------
|
||||||
|
155156 foo
|
||||||
|
|
||||||
|
$ # end of sample session.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
You can also get approximate size data for each object using psql. For
|
||||||
|
example,
|
||||||
|
|
||||||
|
SELECT relpages, relfilenode, relname FROM pg_class ORDER BY relpages DESC;
|
||||||
|
|
||||||
Each page is typically 8k. Relpages is updated by VACUUM.
|
Each page is typically 8k. Relpages is updated by VACUUM.
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
oid2name; a postgresql 7.1 (+?) app to map OIDs on the filesystem
|
* oid2name, a PostgreSQL app to map OIDs on the filesystem
|
||||||
to table and database names.
|
* to table and database names.
|
||||||
|
*
|
||||||
b. palmer, bpalmer@crimelabs.net 1-17-2001
|
* Originally by
|
||||||
|
* B. Palmer, bpalmer@crimelabs.net 1-17-2001
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
|
|
||||||
@ -14,41 +14,46 @@
|
|||||||
|
|
||||||
#include "libpq-fe.h"
|
#include "libpq-fe.h"
|
||||||
|
|
||||||
|
/* an extensible array to keep track of elements to show */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char **array;
|
||||||
|
int num;
|
||||||
|
int alloc;
|
||||||
|
} eary;
|
||||||
|
|
||||||
/* these are the opts structures for command line params */
|
/* these are the opts structures for command line params */
|
||||||
struct options
|
struct options
|
||||||
{
|
{
|
||||||
int getdatabase;
|
eary *tables;
|
||||||
int gettable;
|
eary *oids;
|
||||||
int getoid;
|
eary *filenodes;
|
||||||
|
|
||||||
int quiet;
|
bool quiet;
|
||||||
|
bool systables;
|
||||||
|
bool indexes;
|
||||||
|
bool nodb;
|
||||||
|
bool extended;
|
||||||
|
bool tablespaces;
|
||||||
|
|
||||||
int systables;
|
char *dbname;
|
||||||
|
char *hostname;
|
||||||
int remotehost;
|
char *port;
|
||||||
int remoteport;
|
char *username;
|
||||||
int remoteuser;
|
char *password;
|
||||||
int remotepass;
|
|
||||||
|
|
||||||
int _oid;
|
|
||||||
char _dbname[128];
|
|
||||||
char _tbname[128];
|
|
||||||
|
|
||||||
char _hostname[128];
|
|
||||||
char _port[6];
|
|
||||||
char _username[128];
|
|
||||||
char _password[128];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
void get_opts(int, char **, struct options *);
|
void get_opts(int, char **, struct options *);
|
||||||
PGconn *sql_conn(const char *, struct options *);
|
void *myalloc(size_t size);
|
||||||
void sql_exec_error(int);
|
void add_one_elt(char *eltname, eary *eary);
|
||||||
int sql_exec(PGconn *, const char *, int);
|
char *get_comma_elts(eary *eary);
|
||||||
void sql_exec_dumpdb(PGconn *);
|
PGconn *sql_conn(struct options *);
|
||||||
void sql_exec_dumptable(PGconn *, int);
|
int sql_exec(PGconn *, const char *sql, bool quiet);
|
||||||
void sql_exec_searchtable(PGconn *, const char *);
|
void sql_exec_dumpalldbs(PGconn *, struct options *);
|
||||||
void sql_exec_searchoid(PGconn *, int);
|
void sql_exec_dumpalltables(PGconn *, struct options *);
|
||||||
|
void sql_exec_searchtables(PGconn *, struct options *);
|
||||||
|
void sql_exec_dumpalltbspc(PGconn *, struct options *);
|
||||||
|
|
||||||
/* function to parse command line options and check for some usage errors. */
|
/* function to parse command line options and check for some usage errors. */
|
||||||
void
|
void
|
||||||
@ -57,239 +62,237 @@ get_opts(int argc, char **argv, struct options * my_opts)
|
|||||||
int c;
|
int c;
|
||||||
|
|
||||||
/* set the defaults */
|
/* set the defaults */
|
||||||
my_opts->getdatabase = 0;
|
my_opts->quiet = false;
|
||||||
my_opts->gettable = 0;
|
my_opts->systables = false;
|
||||||
my_opts->getoid = 0;
|
my_opts->indexes = false;
|
||||||
|
my_opts->nodb = false;
|
||||||
my_opts->quiet = 0;
|
my_opts->extended = false;
|
||||||
|
my_opts->tablespaces = false;
|
||||||
my_opts->systables = 0;
|
|
||||||
|
|
||||||
my_opts->remotehost = 0;
|
|
||||||
my_opts->remoteport = 0;
|
|
||||||
my_opts->remoteuser = 0;
|
|
||||||
my_opts->remotepass = 0;
|
|
||||||
|
|
||||||
/* get opts */
|
/* get opts */
|
||||||
while ((c = getopt(argc, argv, "H:p:U:P:d:t:o:qxh?")) != -1)
|
while ((c = getopt(argc, argv, "H:p:U:P:d:t:o:f:qSxish?")) != -1)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
/* specify the database */
|
/* specify the database */
|
||||||
case 'd':
|
case 'd':
|
||||||
my_opts->getdatabase = 1;
|
my_opts->dbname = (char *) myalloc(strlen(optarg));
|
||||||
sscanf(optarg, "%s", my_opts->_dbname);
|
sscanf(optarg, "%s", my_opts->dbname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* specify the table name */
|
/* specify one tablename to show */
|
||||||
case 't':
|
case 't':
|
||||||
/* make sure we set the database first */
|
add_one_elt(optarg, my_opts->tables);
|
||||||
if (!my_opts->getdatabase)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "You must specify a database to dump from.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* make sure we don't try to do a -o also */
|
|
||||||
if (my_opts->getoid)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "You can only specify either oid or table\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
my_opts->gettable = 1;
|
|
||||||
sscanf(optarg, "%s", my_opts->_tbname);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* specify the oid int */
|
/* specify one Oid to show */
|
||||||
case 'o':
|
case 'o':
|
||||||
/* make sure we set the database first */
|
add_one_elt(optarg, my_opts->oids);
|
||||||
if (!my_opts->getdatabase)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "You must specify a database to dump from.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* make sure we don't try to do a -t also */
|
|
||||||
if (my_opts->gettable)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "You can only specify either oid or table\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
my_opts->getoid = 1;
|
|
||||||
sscanf(optarg, "%i", &my_opts->_oid);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* specify one filenode to show*/
|
||||||
|
case 'f':
|
||||||
|
add_one_elt(optarg, my_opts->filenodes);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* don't show headers */
|
||||||
case 'q':
|
case 'q':
|
||||||
my_opts->quiet = 1;
|
my_opts->quiet = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* host to connect to */
|
/* host to connect to */
|
||||||
case 'H':
|
case 'H':
|
||||||
my_opts->remotehost = 1;
|
my_opts->hostname = (char *) myalloc(strlen(optarg));
|
||||||
sscanf(optarg, "%s", my_opts->_hostname);
|
sscanf(optarg, "%s", my_opts->hostname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* port to connect to on remote host */
|
/* port to connect to on remote host */
|
||||||
case 'p':
|
case 'p':
|
||||||
my_opts->remoteport = 1;
|
my_opts->port = (char *) myalloc(strlen(optarg));
|
||||||
sscanf(optarg, "%s", my_opts->_port);
|
sscanf(optarg, "%s", my_opts->port);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* username */
|
/* username */
|
||||||
case 'U':
|
case 'U':
|
||||||
my_opts->remoteuser = 1;
|
my_opts->username = (char *) myalloc(strlen(optarg));
|
||||||
sscanf(optarg, "%s", my_opts->_username);
|
sscanf(optarg, "%s", my_opts->username);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* password */
|
/* password */
|
||||||
case 'P':
|
case 'P':
|
||||||
my_opts->remotepass = 1;
|
my_opts->password = (char *) myalloc(strlen(optarg));
|
||||||
sscanf(optarg, "%s", my_opts->_password);
|
sscanf(optarg, "%s", my_opts->password);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* display system tables */
|
/* display system tables */
|
||||||
|
case 'S':
|
||||||
|
my_opts->systables = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* also display indexes */
|
||||||
|
case 'i':
|
||||||
|
my_opts->indexes = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* display extra columns */
|
||||||
case 'x':
|
case 'x':
|
||||||
my_opts->systables = 1;
|
my_opts->extended = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* dump tablespaces only */
|
||||||
|
case 's':
|
||||||
|
my_opts->tablespaces = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* help! (ugly in code for easier editing) */
|
/* help! (ugly in code for easier editing) */
|
||||||
case '?':
|
case '?':
|
||||||
case 'h':
|
case 'h':
|
||||||
fprintf(stderr, "\
|
fprintf(stderr,
|
||||||
Usage: oid2name [-d database [-x] ] [-t table | -o oid]\n\
|
"Usage: oid2name [-s|-d database] [-S][-i][-q][-x] [-t table|-o oid|-f file] ...\n"
|
||||||
default action display all databases\n\
|
" default action show all database Oids\n"
|
||||||
-d database database to oid2name\n\
|
" -d database database to connect to\n"
|
||||||
-x display system tables\n\
|
" -s show all tablespaces\n"
|
||||||
-t table | -o oid search for table name (-t) or\n\
|
" -S show system objects too\n"
|
||||||
oid (-o) in -d database\n\
|
" -i show indexes and sequences too\n"
|
||||||
-q quiet\n\
|
" -x extended (show additional columns)\n"
|
||||||
-H host connect to remote host\n\
|
" -q quiet (don't show headers)\n"
|
||||||
-p port host port to connect to\n\
|
" -t <table> show info for table named <table>\n"
|
||||||
-U username username to connect with\n\
|
" -o <oid> show info for table with Oid <oid>\n"
|
||||||
-P password password for username\n\
|
" -f <filenode> show info for table with filenode <filenode>\n"
|
||||||
");
|
" -H host connect to remote host\n"
|
||||||
|
" -p port host port to connect to\n"
|
||||||
|
" -U username username to connect with\n"
|
||||||
|
" -P password password for username\n"
|
||||||
|
" (see also $PGPASSWORD and ~/.pgpass)\n"
|
||||||
|
);
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
myalloc(size_t size)
|
||||||
|
{
|
||||||
|
void *ptr = malloc(size);
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "out of memory");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add_one_elt
|
||||||
|
*
|
||||||
|
* Add one element to a (possibly empty) eary struct.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
add_one_elt(char *eltname, eary *eary)
|
||||||
|
{
|
||||||
|
if (eary->alloc == 0)
|
||||||
|
{
|
||||||
|
eary->alloc = 8;
|
||||||
|
eary->array = (char **) myalloc(8 * sizeof(char *));
|
||||||
|
}
|
||||||
|
else if (eary->num >= eary->alloc)
|
||||||
|
{
|
||||||
|
eary->alloc *= 2;
|
||||||
|
eary->array = (char **)
|
||||||
|
realloc(eary->array, eary->alloc * sizeof(char *));
|
||||||
|
if (!eary->array)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "out of memory");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eary->array[eary->num] = strdup(eltname);
|
||||||
|
eary->num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_comma_elts
|
||||||
|
*
|
||||||
|
* Return the elements of an eary as a (freshly allocated) single string, in
|
||||||
|
* single quotes, separated by commas and properly escaped for insertion in an
|
||||||
|
* SQL statement.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
get_comma_elts(eary *eary)
|
||||||
|
{
|
||||||
|
char *ret,
|
||||||
|
*ptr;
|
||||||
|
int i, length = 0;
|
||||||
|
|
||||||
|
if (eary->num == 0)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PQescapeString wants 2 * length + 1 bytes of breath space. Add two
|
||||||
|
* chars per element for the single quotes and one for the comma.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < eary->num; i++)
|
||||||
|
length += strlen(eary->array[i]);
|
||||||
|
|
||||||
|
ret = (char *) myalloc(length * 2 + 4 * eary->num);
|
||||||
|
ptr = ret;
|
||||||
|
|
||||||
|
for (i = 0; i < eary->num; i++)
|
||||||
|
{
|
||||||
|
if (i != 0)
|
||||||
|
sprintf(ptr++, ",");
|
||||||
|
sprintf(ptr++, "'");
|
||||||
|
ptr += PQescapeString(ptr, eary->array[i], strlen(eary->array[i]));
|
||||||
|
sprintf(ptr++, "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* establish connection with database. */
|
/* establish connection with database. */
|
||||||
PGconn *
|
PGconn *
|
||||||
sql_conn(const char *dbName, struct options * my_opts)
|
sql_conn(struct options * my_opts)
|
||||||
{
|
{
|
||||||
char *pghost,
|
|
||||||
*pgport;
|
|
||||||
char *pgoptions,
|
|
||||||
*pgtty;
|
|
||||||
char *pguser,
|
|
||||||
*pgpass;
|
|
||||||
|
|
||||||
PGconn *conn;
|
PGconn *conn;
|
||||||
|
|
||||||
pghost = NULL;
|
|
||||||
pgport = NULL;
|
|
||||||
pgoptions = NULL; /* special options to start up the backend
|
|
||||||
* server */
|
|
||||||
pgtty = NULL; /* debugging tty for the backend server */
|
|
||||||
pguser = NULL;
|
|
||||||
pgpass = NULL;
|
|
||||||
|
|
||||||
/* override the NULLs with the user params if passed */
|
|
||||||
if (my_opts->remotehost)
|
|
||||||
{
|
|
||||||
pghost = (char *) malloc(128);
|
|
||||||
sscanf(my_opts->_hostname, "%s", pghost);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (my_opts->remoteport)
|
|
||||||
{
|
|
||||||
pgport = (char *) malloc(6);
|
|
||||||
sscanf(my_opts->_port, "%s", pgport);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (my_opts->remoteuser)
|
|
||||||
{
|
|
||||||
pguser = (char *) malloc(128);
|
|
||||||
sscanf(my_opts->_username, "%s", pguser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (my_opts->remotepass)
|
|
||||||
{
|
|
||||||
pgpass = (char *) malloc(128);
|
|
||||||
sscanf(my_opts->_password, "%s", pgpass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* login */
|
/* login */
|
||||||
conn = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, pguser, pgpass);
|
conn = PQsetdbLogin(my_opts->hostname,
|
||||||
|
my_opts->port,
|
||||||
|
NULL, /* options */
|
||||||
|
NULL, /* tty */
|
||||||
|
my_opts->dbname,
|
||||||
|
my_opts->username,
|
||||||
|
my_opts->password);
|
||||||
|
|
||||||
/* deal with errors */
|
/* deal with errors */
|
||||||
if (PQstatus(conn) == CONNECTION_BAD)
|
if (PQstatus(conn) != CONNECTION_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
|
fprintf(stderr, "%s: connection to database '%s' failed.\n", "oid2name", my_opts->dbname);
|
||||||
fprintf(stderr, "%s", PQerrorMessage(conn));
|
fprintf(stderr, "%s", PQerrorMessage(conn));
|
||||||
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free data structures: not strictly necessary */
|
|
||||||
if (pghost != NULL)
|
|
||||||
free(pghost);
|
|
||||||
if (pgport != NULL)
|
|
||||||
free(pgport);
|
|
||||||
if (pguser != NULL)
|
|
||||||
free(pguser);
|
|
||||||
if (pgpass != NULL)
|
|
||||||
free(pgpass);
|
|
||||||
|
|
||||||
sql_exec(conn, "SET search_path = public;", 0);
|
|
||||||
|
|
||||||
/* return the conn if good */
|
/* return the conn if good */
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the sql_ command has an error, this function looks up the error number and prints it out. */
|
/*
|
||||||
void
|
* Actual code to make call to the database and print the output data.
|
||||||
sql_exec_error(int error_number)
|
*/
|
||||||
{
|
|
||||||
fprintf(stderr, "Error number %i.\n", error_number);
|
|
||||||
switch (error_number)
|
|
||||||
{
|
|
||||||
case 3:
|
|
||||||
fprintf(stderr, "Error: PGRES_COPY_OUT\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
fprintf(stderr, "Error: PGRES_COPY_IN\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
fprintf(stderr, "Error: PGRES_BAD_RESPONCE\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
fprintf(stderr, "Error: PGRES_NONFATAL_ERROR\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 7:
|
|
||||||
fprintf(stderr, "Error: PGRES_FATAL_ERROR\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* actual code to make call to the database and print the output data */
|
|
||||||
int
|
int
|
||||||
sql_exec(PGconn *conn, const char *todo, int match)
|
sql_exec(PGconn *conn, const char *todo, bool quiet)
|
||||||
{
|
{
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
|
|
||||||
int numbfields;
|
int nfields;
|
||||||
int error_number;
|
int nrows;
|
||||||
int i,
|
int i, j, l;
|
||||||
len;
|
int *length;
|
||||||
|
char *pad;
|
||||||
|
|
||||||
/* make the call */
|
/* make the call */
|
||||||
res = PQexec(conn, todo);
|
res = PQexec(conn, todo);
|
||||||
@ -297,10 +300,8 @@ sql_exec(PGconn *conn, const char *todo, int match)
|
|||||||
/* check and deal with errors */
|
/* check and deal with errors */
|
||||||
if (!res || PQresultStatus(res) > 2)
|
if (!res || PQresultStatus(res) > 2)
|
||||||
{
|
{
|
||||||
error_number = PQresultStatus(res);
|
fprintf(stderr, "oid2name: query failed: %s\n", PQerrorMessage(conn));
|
||||||
fprintf(stderr, "There was an error in the SQL command:\n%s\n", todo);
|
fprintf(stderr, "oid2name: query was: %s\n", todo);
|
||||||
sql_exec_error(error_number);
|
|
||||||
fprintf(stderr, "PQerrorMessage = %s\n", PQerrorMessage(conn));
|
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
@ -308,97 +309,179 @@ sql_exec(PGconn *conn, const char *todo, int match)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get the number of fields */
|
/* get the number of fields */
|
||||||
numbfields = PQntuples(res);
|
nrows = PQntuples(res);
|
||||||
|
nfields = PQnfields(res);
|
||||||
|
|
||||||
/* if we only expect 1 and there mode than, return -2 */
|
/* for each field, get the needed width */
|
||||||
if (match == 1 && numbfields > 1)
|
length = (int *) myalloc(sizeof(int) * nfields);
|
||||||
return -2;
|
for (j = 0; j < nfields; j++)
|
||||||
|
length[j] = strlen(PQfname(res, j));
|
||||||
|
|
||||||
/* return -1 if there aren't any returns */
|
for (i = 0; i < nrows; i++)
|
||||||
if (match == 1 && numbfields < 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* for each row, dump the information */
|
|
||||||
for (i = 0; i < numbfields; i++)
|
|
||||||
{
|
{
|
||||||
len = strlen(PQgetvalue(res, i, 0));
|
for (j = 0; j < nfields; j++)
|
||||||
|
{
|
||||||
fprintf(stdout, "%-6s = %s\n", PQgetvalue(res, i, 0), PQgetvalue(res, i, 1));
|
l = strlen(PQgetvalue(res, i, j));
|
||||||
|
if (l > length[j])
|
||||||
|
length[j] = strlen(PQgetvalue(res, i, j));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean the PGconn once done */
|
/* print a header */
|
||||||
|
if (!quiet)
|
||||||
|
{
|
||||||
|
for (j = 0, l = 0; j < nfields; j++)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "%*s", length[j] + 2, PQfname(res, j));
|
||||||
|
l += length[j] + 2;
|
||||||
|
}
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
pad = (char *) myalloc(l + 1);
|
||||||
|
MemSet(pad, '-', l);
|
||||||
|
pad[l] = '\0';
|
||||||
|
fprintf(stdout, "%s\n", pad);
|
||||||
|
free(pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for each row, dump the information */
|
||||||
|
for (i = 0; i < nrows; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < nfields; j++)
|
||||||
|
fprintf(stdout, "%*s", length[j] + 2, PQgetvalue(res, i, j));
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
free(length);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dump all databases known by the system table */
|
/*
|
||||||
|
* Dump all databases. There are no system objects to worry about.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
sql_exec_dumpdb(PGconn *conn)
|
sql_exec_dumpalldbs(PGconn *conn, struct options *opts)
|
||||||
{
|
{
|
||||||
char todo[1024];
|
char todo[1024];
|
||||||
|
|
||||||
/* get the oid and database name from the system pg_database table */
|
/* get the oid and database name from the system pg_database table */
|
||||||
snprintf(todo, 1024, "select oid,datname from pg_database");
|
snprintf(todo, 1024, "SELECT d.oid AS \"Oid\", datname AS \"Database Name\", "
|
||||||
|
"spcname AS \"Tablespace\" FROM pg_database d JOIN pg_tablespace t ON "
|
||||||
|
"(dattablespace = t.oid) ORDER BY 2");
|
||||||
|
|
||||||
sql_exec(conn, todo, 0);
|
sql_exec(conn, todo, opts->quiet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* display all tables in whatever db we are connected to. don't display the
|
/*
|
||||||
system tables by default */
|
* Dump all tables, indexes and sequences in the current database.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
sql_exec_dumptable(PGconn *conn, int systables)
|
sql_exec_dumpalltables(PGconn *conn, struct options *opts)
|
||||||
|
{
|
||||||
|
char todo[1024];
|
||||||
|
char *addfields = ",c.oid AS \"Oid\", nspname AS \"Schema\", spcname as \"Tablespace\" ";
|
||||||
|
|
||||||
|
snprintf(todo, 1024,
|
||||||
|
"SELECT relfilenode as \"Filenode\", relname as \"Table Name\" %s "
|
||||||
|
"FROM pg_class c "
|
||||||
|
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace "
|
||||||
|
" LEFT JOIN pg_catalog.pg_database d ON d.datname = current_database(),"
|
||||||
|
" pg_catalog.pg_tablespace t "
|
||||||
|
"WHERE relkind IN ('r'%s) AND "
|
||||||
|
" %s"
|
||||||
|
" t.oid = CASE"
|
||||||
|
" WHEN reltablespace <> 0 THEN reltablespace"
|
||||||
|
" WHEN n.nsptablespace <> 0 THEN nsptablespace"
|
||||||
|
" WHEN d.dattablespace <> 0 THEN dattablespace"
|
||||||
|
" END "
|
||||||
|
"ORDER BY relname",
|
||||||
|
opts->extended ? addfields : "",
|
||||||
|
opts->indexes ? ", 'i', 'S', 't'" : "",
|
||||||
|
opts->systables ? "" : "n.nspname NOT IN ('pg_catalog', 'pg_toast', 'information_schema') AND");
|
||||||
|
|
||||||
|
sql_exec(conn, todo, opts->quiet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Show oid, relfilenode, name, schema and tablespace for each of the
|
||||||
|
* given objects in the current database.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sql_exec_searchtables(PGconn *conn, struct options *opts)
|
||||||
|
{
|
||||||
|
char *todo;
|
||||||
|
char *qualifiers, *ptr;
|
||||||
|
char *comma_oids, *comma_filenodes, *comma_tables;
|
||||||
|
bool written = false;
|
||||||
|
char *addfields = ",c.oid AS \"Oid\", nspname AS \"Schema\", spcname as \"Tablespace\" ";
|
||||||
|
|
||||||
|
/* get tables qualifiers, whether names, relfilenodes, or OIDs */
|
||||||
|
comma_oids = get_comma_elts(opts->oids);
|
||||||
|
comma_tables = get_comma_elts(opts->tables);
|
||||||
|
comma_filenodes = get_comma_elts(opts->filenodes);
|
||||||
|
|
||||||
|
/* 80 extra chars for SQL expression */
|
||||||
|
qualifiers = (char *) myalloc(strlen(comma_oids) + strlen(comma_tables) +
|
||||||
|
strlen(comma_filenodes) + 80);
|
||||||
|
ptr = qualifiers;
|
||||||
|
|
||||||
|
if (opts->oids->num > 0)
|
||||||
|
{
|
||||||
|
ptr += sprintf(ptr, "c.oid IN (%s)", comma_oids);
|
||||||
|
written = true;
|
||||||
|
}
|
||||||
|
if (opts->filenodes->num > 0)
|
||||||
|
{
|
||||||
|
if (written)
|
||||||
|
ptr += sprintf(ptr, " OR ");
|
||||||
|
ptr += sprintf(ptr, "c.relfilenode IN (%s)", comma_filenodes);
|
||||||
|
written = true;
|
||||||
|
}
|
||||||
|
if (opts->tables->num > 0)
|
||||||
|
{
|
||||||
|
if (written)
|
||||||
|
ptr += sprintf(ptr, " OR ");
|
||||||
|
sprintf(ptr, "c.relname ~~ ANY (ARRAY[%s])", comma_tables);
|
||||||
|
}
|
||||||
|
free(comma_oids);
|
||||||
|
free(comma_tables);
|
||||||
|
free(comma_filenodes);
|
||||||
|
|
||||||
|
/* now build the query */
|
||||||
|
todo = (char *) myalloc(650 + strlen(qualifiers));
|
||||||
|
snprintf(todo, 1024,
|
||||||
|
"SELECT relfilenode as \"Filenode\", relname as \"Table Name\" %s\n"
|
||||||
|
"FROM pg_class c \n"
|
||||||
|
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n"
|
||||||
|
" LEFT JOIN pg_catalog.pg_database d ON d.datname = current_database(),\n"
|
||||||
|
" pg_catalog.pg_tablespace t \n"
|
||||||
|
"WHERE relkind IN ('r', 'i', 'S', 't') AND \n"
|
||||||
|
" t.oid = CASE\n"
|
||||||
|
" WHEN reltablespace <> 0 THEN reltablespace\n"
|
||||||
|
" WHEN n.nsptablespace <> 0 THEN nsptablespace\n"
|
||||||
|
" WHEN d.dattablespace <> 0 THEN dattablespace\n"
|
||||||
|
" END AND \n"
|
||||||
|
" (%s) \n"
|
||||||
|
"ORDER BY relname\n",
|
||||||
|
opts->extended ? addfields : "",
|
||||||
|
qualifiers);
|
||||||
|
|
||||||
|
free(qualifiers);
|
||||||
|
|
||||||
|
sql_exec(conn, todo, opts->quiet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sql_exec_dumpalltbspc(PGconn *conn, struct options *opts)
|
||||||
{
|
{
|
||||||
char todo[1024];
|
char todo[1024];
|
||||||
|
|
||||||
/* don't exclude the systables if this is set */
|
snprintf(todo, 1024, "SELECT oid AS \"Oid\", spcname as \"Tablespace Name\"\n"
|
||||||
if (systables == 1)
|
"FROM pg_tablespace");
|
||||||
snprintf(todo, 1024, "select relfilenode,relname from pg_class order by relname");
|
|
||||||
else
|
|
||||||
snprintf(todo, 1024, "select relfilenode,relname from pg_class "
|
|
||||||
"where relkind not in ('v','s', 'c') and "
|
|
||||||
"relname not like 'pg_%%' order by relname");
|
|
||||||
|
|
||||||
sql_exec(conn, todo, 0);
|
sql_exec(conn, todo, opts->quiet);
|
||||||
}
|
|
||||||
|
|
||||||
/* display the oid for a given tablename for whatever db we are connected
|
|
||||||
to. do we want to allow %bar% in the search? Not now. */
|
|
||||||
void
|
|
||||||
sql_exec_searchtable(PGconn *conn, const char *tablename)
|
|
||||||
{
|
|
||||||
int returnvalue;
|
|
||||||
char todo[1024];
|
|
||||||
|
|
||||||
/* get the oid and tablename where the name matches tablename */
|
|
||||||
snprintf(todo, 1024, "select relfilenode,relname from pg_class where relname = '%s'", tablename);
|
|
||||||
|
|
||||||
returnvalue = sql_exec(conn, todo, 1);
|
|
||||||
|
|
||||||
/* deal with the return errors */
|
|
||||||
if (returnvalue == -1)
|
|
||||||
printf("No tables with that name found\n");
|
|
||||||
|
|
||||||
if (returnvalue == -2)
|
|
||||||
printf("VERY scary: more than one table with that name found!!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* same as above */
|
|
||||||
void
|
|
||||||
sql_exec_searchoid(PGconn *conn, int oid)
|
|
||||||
{
|
|
||||||
int returnvalue;
|
|
||||||
char todo[1024];
|
|
||||||
|
|
||||||
snprintf(todo, 1024, "select relfilenode,relname from pg_class where oid = %i", oid);
|
|
||||||
|
|
||||||
returnvalue = sql_exec(conn, todo, 1);
|
|
||||||
|
|
||||||
if (returnvalue == -1)
|
|
||||||
printf("No tables with that oid found\n");
|
|
||||||
|
|
||||||
if (returnvalue == -2)
|
|
||||||
printf("VERY scary: more than one table with that oid found!!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -407,65 +490,66 @@ main(int argc, char **argv)
|
|||||||
struct options *my_opts;
|
struct options *my_opts;
|
||||||
PGconn *pgconn;
|
PGconn *pgconn;
|
||||||
|
|
||||||
my_opts = (struct options *) malloc(sizeof(struct options));
|
my_opts = (struct options *) myalloc(sizeof(struct options));
|
||||||
|
|
||||||
|
my_opts->oids = (eary *) myalloc(sizeof(eary));
|
||||||
|
my_opts->tables = (eary *) myalloc(sizeof(eary));
|
||||||
|
my_opts->filenodes = (eary *) myalloc(sizeof(eary));
|
||||||
|
|
||||||
|
my_opts->oids->num = my_opts->oids->alloc = 0;
|
||||||
|
my_opts->tables->num = my_opts->tables->alloc = 0;
|
||||||
|
my_opts->filenodes->num = my_opts->filenodes->alloc = 0;
|
||||||
|
|
||||||
/* parse the opts */
|
/* parse the opts */
|
||||||
get_opts(argc, argv, my_opts);
|
get_opts(argc, argv, my_opts);
|
||||||
|
|
||||||
/* display all the tables in the database */
|
if (my_opts->dbname == NULL)
|
||||||
if (my_opts->getdatabase & my_opts->gettable)
|
{
|
||||||
|
my_opts->dbname = "template1";
|
||||||
|
my_opts->nodb = true;
|
||||||
|
}
|
||||||
|
pgconn = sql_conn(my_opts);
|
||||||
|
|
||||||
|
/* display only tablespaces */
|
||||||
|
if (my_opts->tablespaces)
|
||||||
{
|
{
|
||||||
if (!my_opts->quiet)
|
if (!my_opts->quiet)
|
||||||
{
|
printf("All tablespaces:\n");
|
||||||
printf("Oid of table %s from database \"%s\":\n", my_opts->_tbname, my_opts->_dbname);
|
sql_exec_dumpalltbspc(pgconn, my_opts);
|
||||||
printf("---------------------------------\n");
|
|
||||||
}
|
PQfinish(pgconn);
|
||||||
pgconn = sql_conn(my_opts->_dbname, my_opts);
|
exit(0);
|
||||||
sql_exec_searchtable(pgconn, my_opts->_tbname);
|
}
|
||||||
|
|
||||||
|
/* display the given elements in the database */
|
||||||
|
if (my_opts->oids->num > 0 ||
|
||||||
|
my_opts->tables->num > 0 ||
|
||||||
|
my_opts->filenodes->num > 0)
|
||||||
|
{
|
||||||
|
if (!my_opts->quiet)
|
||||||
|
printf("From database \"%s\":\n", my_opts->dbname);
|
||||||
|
sql_exec_searchtables(pgconn, my_opts);
|
||||||
|
|
||||||
|
PQfinish(pgconn);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no elements given; dump the given database */
|
||||||
|
if (my_opts->dbname && !my_opts->nodb)
|
||||||
|
{
|
||||||
|
if (!my_opts->quiet)
|
||||||
|
printf("From database \"%s\":\n", my_opts->dbname);
|
||||||
|
sql_exec_dumpalltables(pgconn, my_opts);
|
||||||
|
|
||||||
|
PQfinish(pgconn);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no database either; dump all databases */
|
||||||
|
if (!my_opts->quiet)
|
||||||
|
printf("All databases:\n");
|
||||||
|
sql_exec_dumpalldbs(pgconn, my_opts);
|
||||||
|
|
||||||
PQfinish(pgconn);
|
PQfinish(pgconn);
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* search for the tablename of the given OID */
|
|
||||||
if (my_opts->getdatabase & my_opts->getoid)
|
|
||||||
{
|
|
||||||
if (!my_opts->quiet)
|
|
||||||
{
|
|
||||||
printf("Tablename of oid %i from database \"%s\":\n", my_opts->_oid, my_opts->_dbname);
|
|
||||||
printf("---------------------------------\n");
|
|
||||||
}
|
|
||||||
pgconn = sql_conn(my_opts->_dbname, my_opts);
|
|
||||||
sql_exec_searchoid(pgconn, my_opts->_oid);
|
|
||||||
PQfinish(pgconn);
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* search for the oid for the given tablename */
|
|
||||||
if (my_opts->getdatabase)
|
|
||||||
{
|
|
||||||
if (!my_opts->quiet)
|
|
||||||
{
|
|
||||||
printf("All tables from database \"%s\":\n", my_opts->_dbname);
|
|
||||||
printf("---------------------------------\n");
|
|
||||||
}
|
|
||||||
pgconn = sql_conn(my_opts->_dbname, my_opts);
|
|
||||||
sql_exec_dumptable(pgconn, my_opts->systables);
|
|
||||||
PQfinish(pgconn);
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* display all the databases for the server we are connected to.. */
|
|
||||||
if (!my_opts->quiet)
|
|
||||||
{
|
|
||||||
printf("All databases:\n");
|
|
||||||
printf("---------------------------------\n");
|
|
||||||
}
|
|
||||||
pgconn = sql_conn("template1", my_opts);
|
|
||||||
sql_exec_dumpdb(pgconn);
|
|
||||||
PQfinish(pgconn);
|
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user