Index: README.oid2name =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/contrib/oid2name/README.oid2name,v retrieving revision 1.9 diff -c -r1.9 README.oid2name *** README.oid2name 12 Oct 2002 19:15:09 -0000 1.9 --- README.oid2name 14 Sep 2004 18:31:34 -0000 *************** *** 1,124 **** This utility allows administrators to view the file structure used by ! PostgreSQL. Databases are placed in directories based on their OIDs in ! 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. ! --------------------------------------------------------------------------- ! ! It can be used in four ways: ! ! ! oid2name ! ! This will connect to the template1 database and display all databases ! in the system: ! ! $ oid2name ! All databases: ! --------------------------------- ! 18720 = test1 ! 1 = template1 ! 18719 = template0 ! 18721 = test ! 18735 = postgres ! 18736 = cssi ! ! ! oid2name -d test [-x] ! ! This connects to the database test and shows all tables and their OIDs: ! ! $ oid2name -d test ! All tables from database "test": ! --------------------------------- ! 18766 = dns ! 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: - $ cd /u/pg/data/base $ oid2name All databases: ! --------------------------------- ! 16817 = test2 ! 16578 = x ! 16756 = test ! 1 = template1 ! 16569 = template0 ! 16818 = test3 ! 16811 = floattest ! ! $ cd 16756 ! $ ls 1873* ! 18730 18731 18732 18735 18736 18737 18738 18739 ! ! $ oid2name -d test -o 18737 ! Tablename of oid 18737 from database "test": ! --------------------------------- ! 18737 = ips ! ! $ oid2name -d test -t ips ! Oid of table ips from database "test": ! --------------------------------- ! 18737 = ips $ # show disk space for every db object ! $ du * | while read SIZE OID > do ! > echo "$SIZE `oid2name -q -d test -o $OID`" > done ! 24 18737 = ips ! 36 18722 = cities ... ! $ # same as above, but sort by largest first ! $ du * | while read SIZE OID > do ! > echo "$SIZE `oid2name -q -d test -o $OID`" ! > done | ! > sort -rn ! 2048 19324 = bigtable ! 1950 23903 = customers ... ! $ # show disk usage per database ! $ cd /u/pg/data/base ! $ du -s * | ! > while read SIZE OID ! > do ! > echo "$SIZE `aspg oid2name -q | grep ^$OID' '`" ! > done | ! > sort -rn ! 2256 18721 = test ! 2135 18735 = postgres ! .. ! This can be done in psql with: test=> SELECT relpages, relfilenode, relname FROM pg_class ORDER BY relpages DESC; --- 1,170 ---- This utility allows administrators to view the file structure used by ! PostgreSQL. ! Databases are placed in directories based on their OIDs in pg_database, ! and the tables in that directory are named by original OIDs, stored in ! pg_class.relfilenode. ! ! Tablespaces make the scenario more complicated. Each tablespace has a ! directory inside the pg_tblspc directory, with a symlink pointing to the ! actual tablespace directory. Inside that directory there is another ! directory for each database that has elements in the tablespace, named ! after the database's OID. ! ! Oid2name connects to the database and extracts the OID and table name ! information. You can also have it show the database OIDs and tablespace ! OIDs. ! ! When displaying tables (i.e. not all databases, not tablespaces, and not ! a whole database) you can select which tables to show by using -o, -f ! and -t. The first switch receives an OID, the second receives a ! filename, and the third receives a tablename (actually, it's a LIKE ! pattern, so you can use things like "foo%"). Note that you can use as ! many of these switches as you like, and the listing will include all ! relevant objects. ! ! Note that while OID and filename sometimes match, this is not ! necessarily the case; some operations, like TRUNCATE, REINDEX, CLUSTER ! and some forms of ALTER TABLE can change the filename while preserving ! the OID. ! ! Additional switches: ! -i include indexes and sequences in the database listing. ! -x display more information about each object shown: ! tablespace name, schema name, OID. ! -S also show system objects ! (those in information_schema, pg_toast and pg_catalog schemas) ! -q don't display headers ! (useful for scripting) ! -s show a tablespace listing instead ! If you don't give any of -t, -f or -o it will dump the whole database ! given in -d. If you don't give -d, it will show a database listing. --------------------------------------------------------------------------- Sample session: $ oid2name All databases: ! Oid Database Name Tablespace ! ---------------------------------- ! 17228 alvherre pg_default ! 17255 regression pg_default ! 17227 template0 pg_default ! 1 template1 pg_default ! ! $ oid2name -s ! All tablespaces: ! Oid Tablespace Name ! ------------------------- ! 1663 pg_default ! 1664 pg_global ! 155151 fastdisk ! 155152 bigdisk ! ! $ cd $PGDATA/17228 ! ! $ # get top 10 db objects in the default tablespace, ordered by size ! $ ls -lS * | head -10 ! -rw------- 1 alvherre alvherre 136536064 sep 14 09:51 155173 ! -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 ! $ du [0-9]* | ! > while read SIZE OID > do ! > echo "$SIZE `oid2name -q -d alvherre -i -f $OID`" > done ! 16 1155287 branches_pkey ! 16 1155289 tellers_pkey ! 17561 1155291 accounts_pkey ... ! $ # same, but sort by size ! $ du [0-9]* | sort -rn | while read SIZE FN > do ! > echo "$SIZE `oid2name -q -d alvherre -f $FN`" ! > done ! 133466 155173 accounts ! 17561 1155291 accounts_pkey ! 1177 16717 pg_proc_proname_args_nsp_index ... ! $ # If you want to see what's in tablespaces, use the pg_tblspc directory ! $ cd $PGDATA/pg_tblspc ! $ oid2name -s ! All tablespaces: ! Oid Tablespace Name ! ------------------------- ! 1663 pg_default ! 1664 pg_global ! 155151 fastdisk ! 155152 bigdisk ! ! $ # what databases have objects in tablespace "fastdisk"? ! $ ls -d 155151/* ! 155151/17228/ 155151/PG_VERSION ! ! $ # 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 has 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, test=> SELECT relpages, relfilenode, relname FROM pg_class ORDER BY relpages DESC; Index: oid2name.c =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/contrib/oid2name/oid2name.c,v retrieving revision 1.23 diff -c -r1.23 oid2name.c *** oid2name.c 3 Mar 2004 14:24:12 -0000 1.23 --- oid2name.c 14 Sep 2004 18:46:37 -0000 *************** *** 1,9 **** /* ! oid2name; a postgresql 7.1 (+?) app to map OIDs on the filesystem ! to table and database names. ! ! b. palmer, bpalmer@crimelabs.net 1-17-2001 ! */ #include "postgres_fe.h" --- 1,9 ---- /* ! * oid2name, a PostgreSQL app to map OIDs on the filesystem ! * to table and database names. ! * ! * Originally by ! * B. Palmer, bpalmer@crimelabs.net 1-17-2001 */ #include "postgres_fe.h" *************** *** 14,54 **** #include "libpq-fe.h" /* these are the opts structures for command line params */ struct options { ! int getdatabase; ! int gettable; ! int getoid; ! ! int quiet; ! ! int systables; ! ! int remotehost; ! int remoteport; ! int remoteuser; ! int remotepass; ! ! int _oid; ! char _dbname[128]; ! char _tbname[128]; ! ! char _hostname[128]; ! char _port[6]; ! char _username[128]; ! char _password[128]; }; /* function prototypes */ void get_opts(int, char **, struct options *); ! PGconn *sql_conn(const char *, struct options *); ! void sql_exec_error(int); ! int sql_exec(PGconn *, const char *, int); ! void sql_exec_dumpdb(PGconn *); ! void sql_exec_dumptable(PGconn *, int); ! void sql_exec_searchtable(PGconn *, const char *); ! void sql_exec_searchoid(PGconn *, int); /* function to parse command line options and check for some usage errors. */ void --- 14,59 ---- #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 */ struct options { ! eary *tables; ! eary *oids; ! eary *filenodes; ! ! bool quiet; ! bool systables; ! bool indexes; ! bool nodb; ! bool extended; ! bool tablespaces; ! ! char *dbname; ! char *hostname; ! char *port; ! char *username; ! char *password; }; /* function prototypes */ void get_opts(int, char **, struct options *); ! void *myalloc(size_t size); ! void add_one_elt(char *eltname, eary *eary); ! char *get_comma_elts(eary *eary); ! PGconn *sql_conn(struct options *); ! int sql_exec(PGconn *, const char *sql, bool quiet); ! void sql_exec_dumpalldbs(PGconn *, struct options *); ! 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. */ void *************** *** 57,295 **** int c; /* set the defaults */ ! my_opts->getdatabase = 0; ! my_opts->gettable = 0; ! my_opts->getoid = 0; ! ! my_opts->quiet = 0; ! ! my_opts->systables = 0; ! ! my_opts->remotehost = 0; ! my_opts->remoteport = 0; ! my_opts->remoteuser = 0; ! my_opts->remotepass = 0; /* get opts */ ! while ((c = getopt(argc, argv, "H:p:U:P:d:t:o:qxh?")) != -1) { switch (c) { /* specify the database */ case 'd': ! my_opts->getdatabase = 1; ! sscanf(optarg, "%s", my_opts->_dbname); break; ! /* specify the table name */ case 't': ! /* make sure we set the database first */ ! 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; ! /* specify the oid int */ case 'o': ! /* make sure we set the database first */ ! 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; case 'q': ! my_opts->quiet = 1; break; /* host to connect to */ case 'H': ! my_opts->remotehost = 1; ! sscanf(optarg, "%s", my_opts->_hostname); break; /* port to connect to on remote host */ case 'p': ! my_opts->remoteport = 1; ! sscanf(optarg, "%s", my_opts->_port); break; /* username */ case 'U': ! my_opts->remoteuser = 1; ! sscanf(optarg, "%s", my_opts->_username); break; /* password */ case 'P': ! my_opts->remotepass = 1; ! sscanf(optarg, "%s", my_opts->_password); break; /* display system tables */ case 'x': ! my_opts->systables = 1; break; /* help! (ugly in code for easier editing) */ case '?': case 'h': ! fprintf(stderr, "\ ! Usage: oid2name [-d database [-x] ] [-t table | -o oid]\n\ ! default action display all databases\n\ ! -d database database to oid2name\n\ ! -x display system tables\n\ ! -t table | -o oid search for table name (-t) or\n\ ! oid (-o) in -d database\n\ ! -q quiet\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\ ! "); exit(1); break; } } } ! /* establish connection with database. */ ! PGconn * ! sql_conn(const char *dbName, struct options * my_opts) { ! char *pghost, ! *pgport; ! char *pgoptions, ! *pgtty; ! char *pguser, ! *pgpass; ! ! 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 */ ! conn = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, pguser, pgpass); /* deal with errors */ ! if (PQstatus(conn) == CONNECTION_BAD) { ! fprintf(stderr, "Connection to database '%s' failed.\n", dbName); fprintf(stderr, "%s", PQerrorMessage(conn)); PQfinish(conn); 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 conn; } ! /* If the sql_ command has an error, this function looks up the error number and prints it out. */ ! void ! 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 ! sql_exec(PGconn *conn, const char *todo, int match) { PGresult *res; ! int numbfields; ! int error_number; ! int i, ! len; /* make the call */ res = PQexec(conn, todo); --- 62,298 ---- int c; /* set the defaults */ ! my_opts->quiet = false; ! my_opts->systables = false; ! my_opts->indexes = false; ! my_opts->nodb = false; ! my_opts->extended = false; ! my_opts->tablespaces = false; /* get opts */ ! while ((c = getopt(argc, argv, "H:p:U:P:d:t:o:f:qSxish?")) != -1) { switch (c) { /* specify the database */ case 'd': ! my_opts->dbname = (char *) myalloc(strlen(optarg)); ! sscanf(optarg, "%s", my_opts->dbname); break; ! /* specify one tablename to show */ case 't': ! add_one_elt(optarg, my_opts->tables); break; ! /* specify one Oid to show */ case 'o': ! add_one_elt(optarg, my_opts->oids); ! break; + /* specify one filenode to show*/ + case 'f': + add_one_elt(optarg, my_opts->filenodes); break; + /* don't show headers */ case 'q': ! my_opts->quiet = true; break; /* host to connect to */ case 'H': ! my_opts->hostname = (char *) myalloc(strlen(optarg)); ! sscanf(optarg, "%s", my_opts->hostname); break; /* port to connect to on remote host */ case 'p': ! my_opts->port = (char *) myalloc(strlen(optarg)); ! sscanf(optarg, "%s", my_opts->port); break; /* username */ case 'U': ! my_opts->username = (char *) myalloc(strlen(optarg)); ! sscanf(optarg, "%s", my_opts->username); break; /* password */ case 'P': ! my_opts->password = (char *) myalloc(strlen(optarg)); ! sscanf(optarg, "%s", my_opts->password); break; /* 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': ! my_opts->extended = true; ! break; ! ! /* dump tablespaces only */ ! case 's': ! my_opts->tablespaces = true; break; /* help! (ugly in code for easier editing) */ case '?': case 'h': ! fprintf(stderr, ! "Usage: oid2name [-s|-d database] [-S][-i][-q][-x] [-t table|-o oid|-f file] ...\n" ! " default action show all database Oids\n" ! " -d database database to connect to\n" ! " -s show all tablespaces\n" ! " -S show system objects too\n" ! " -i show indexes and sequences too\n" ! " -x extended (show additional columns)\n" ! " -q quiet (don't show headers)\n" ! " -t