]> granicus.if.org Git - postgresql/blob - contrib/oid2name/oid2name.c
Currently, contrib/oid2name doesn't bother to free() the memory that it
[postgresql] / contrib / oid2name / oid2name.c
1 /*
2   oid2name; a postgresql 7.1 (+?) app to map OIDs on the filesystem
3    to table and database names.
4
5   b. palmer, bpalmer@crimelabs.net 1-17-2001
6
7  */
8 #include "postgres_fe.h"
9
10 #include <unistd.h>
11 #ifdef HAVE_GETOPT_H
12 #include <getopt.h>
13 #endif
14
15 #include "libpq-fe.h"
16
17 /* these are the opts structures for command line params */
18 struct options
19 {
20         int                     getdatabase;
21         int                     gettable;
22         int                     getoid;
23
24         int                     systables;
25
26         int                     remotehost;
27         int                     remoteport;
28         int                     remoteuser;
29         int                     remotepass;
30
31         int                     _oid;
32         char            _dbname[128];
33         char            _tbname[128];
34
35         char            _hostname[128];
36         char            _port[6];
37         char            _username[128];
38         char            _password[128];
39 };
40
41 /* function prototypes */
42 void            get_opts(int, char **, struct options *);
43 PGconn     *sql_conn(const char *, struct options *);
44 void            sql_exec_error(int);
45 int                     sql_exec(PGconn *, const char *, int);
46 void            sql_exec_dumpdb(PGconn *);
47 void            sql_exec_dumptable(PGconn *, int);
48 void            sql_exec_searchtable(PGconn *, const char *);
49 void            sql_exec_searchoid(PGconn *, int);
50
51 /* fuction to parse command line options and check for some usage errors. */
52 void
53 get_opts(int argc, char **argv, struct options * my_opts)
54 {
55         int                     c;
56
57         /* set the defaults */
58         my_opts->getdatabase = 0;
59         my_opts->gettable = 0;
60         my_opts->getoid = 0;
61
62         my_opts->systables = 0;
63
64         my_opts->remotehost = 0;
65         my_opts->remoteport = 0;
66         my_opts->remoteuser = 0;
67         my_opts->remotepass = 0;
68
69         /* get opts */
70         while ((c = getopt(argc, argv, "H:p:U:P:d:t:o:xh?")) != -1)
71         {
72                 switch (c)
73                 {
74                                 /* specify the database */
75                         case 'd':
76                                 my_opts->getdatabase = 1;
77                                 sscanf(optarg, "%s", my_opts->_dbname);
78                                 break;
79
80                                 /* specify the table name */
81                         case 't':
82                                 /* make sure we set the database first */
83                                 if (!my_opts->getdatabase)
84                                 {
85                                         fprintf(stderr, "Sorry,  but you must specify a database to dump from.\n");
86                                         exit(1);
87                                 }
88                                 /* make sure we don't try to do a -o also */
89                                 if (my_opts->getoid)
90                                 {
91                                         fprintf(stderr, "Sorry, you can only specify either oid or table\n");
92                                         exit(1);
93                                 }
94
95                                 my_opts->gettable = 1;
96                                 sscanf(optarg, "%s", my_opts->_tbname);
97
98                                 break;
99
100                                 /* specify the oid int */
101                         case 'o':
102                                 /* make sure we set the database first */
103                                 if (!my_opts->getdatabase)
104                                 {
105                                         fprintf(stderr, "Sorry,  but you must specify a database to dump from.\n");
106                                         exit(1);
107                                 }
108                                 /* make sure we don't try to do a -t also */
109                                 if (my_opts->gettable)
110                                 {
111                                         fprintf(stderr, "Sorry, you can only specify either oid or table\n");
112                                         exit(1);
113                                 }
114
115                                 my_opts->getoid = 1;
116                                 sscanf(optarg, "%i", &my_opts->_oid);
117
118                                 break;
119
120                                 /* host to connect to */
121                         case 'H':
122                                 my_opts->remotehost = 1;
123                                 sscanf(optarg, "%s", my_opts->_hostname);
124                                 break;
125
126                                 /* port to connect to on remote host */
127                         case 'p':
128                                 my_opts->remoteport = 1;
129                                 sscanf(optarg, "%s", my_opts->_port);
130                                 break;
131
132                                 /* username */
133                         case 'U':
134                                 my_opts->remoteuser = 1;
135                                 sscanf(optarg, "%s", my_opts->_username);
136                                 break;
137
138                                 /* password */
139                         case 'P':
140                                 my_opts->remotepass = 1;
141                                 sscanf(optarg, "%s", my_opts->_password);
142                                 break;
143
144                                 /* display system tables */
145                         case 'x':
146                                 my_opts->systables = 1;
147                                 break;
148
149                                 /* help! (ugly in code for easier editing) */
150                         case '?':
151                         case 'h':
152                                 fprintf(stderr, "\n\
153 Usage: pg_oid2name [-d database [-x] ] [-t table | -o oid] \n\
154         default action        display all databases\n\
155         -d database           database to oid2name\n\
156         -x                    display system tables\n\
157         -t table | -o oid     search for table name (-t) or\n\
158                                oid (-o) in -d database\n\
159         -H host               connect to remote host\n\
160         -p port               host port to connect to\n\
161         -U username           username to connect with\n\
162         -P password           password for username\n\n\
163 ");
164                                 exit(1);
165                                 break;
166                 }
167         }
168 }
169
170 /* establish connection with database. */
171 PGconn *
172 sql_conn(const char *dbName, struct options * my_opts)
173 {
174         char       *pghost,
175                            *pgport;
176         char       *pgoptions,
177                            *pgtty;
178         char       *pguser,
179                            *pgpass;
180
181         PGconn     *conn;
182
183         pghost = NULL;
184         pgport = NULL;
185         pgoptions = NULL;                       /* special options to start up the backend
186                                                                  * server */
187         pgtty = NULL;                           /* debugging tty for the backend server */
188         pguser = NULL;
189         pgpass = NULL;
190
191         /* override the NULLs with the user params if passed */
192         if (my_opts->remotehost)
193         {
194                 pghost = (char *) malloc(128);
195                 sscanf(my_opts->_hostname, "%s", pghost);
196         }
197
198         if (my_opts->remoteport)
199         {
200                 pgport = (char *) malloc(6);
201                 sscanf(my_opts->_port, "%s", pgport);
202         }
203
204         if (my_opts->remoteuser)
205         {
206                 pguser = (char *) malloc(128);
207                 sscanf(my_opts->_username, "%s", pguser);
208         }
209
210         if (my_opts->remotepass)
211         {
212                 pgpass = (char *) malloc(128);
213                 sscanf(my_opts->_password, "%s", pgpass);
214         }
215
216         /* login */
217         conn = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, pguser, pgpass);
218
219         /* deal with errors */
220         if (PQstatus(conn) == CONNECTION_BAD)
221         {
222                 fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
223                 fprintf(stderr, "%s", PQerrorMessage(conn));
224
225                 PQfinish(conn);
226                 exit(1);
227         }
228
229         /* free data structures: not strictly necessary */
230         if (pghost != NULL)
231                 free(pghost);
232         if (pgport != NULL)
233                 free(pgport);
234         if (pguser != NULL)
235                 free(pguser);
236         if (pgpass != NULL)
237                 free(pgpass);
238
239         /* return the conn if good */
240         return conn;
241 }
242
243 /* If the sql_ command has an error,  this function looks up the error number and prints it out. */
244 void
245 sql_exec_error(int error_number)
246 {
247         fprintf(stderr, "Error number %i.\n", error_number);
248         switch (error_number)
249         {
250                 case 3:
251                         fprintf(stderr, "Error:  PGRES_COPY_OUT\n");
252                         break;
253
254                 case 4:
255                         fprintf(stderr, "Error:  PGRES_COPY_IN\n");
256                         break;
257
258                 case 5:
259                         fprintf(stderr, "Error:  PGRES_BAD_RESPONCE\n");
260                         break;
261
262                 case 6:
263                         fprintf(stderr, "Error:  PGRES_NONFATAL_ERROR\n");
264                         break;
265
266                 case 7:
267                         fprintf(stderr, "Error:  PGRES_FATAL_ERROR\n");
268                         break;
269         }
270 }
271
272 /* actual code to make call to the database and print the output data */
273 int
274 sql_exec(PGconn *conn, const char *todo, int match)
275 {
276         PGresult   *res;
277
278         int                     numbfields;
279         int                     error_number;
280         int                     i,
281                                 len;
282
283         /* make the call */
284         res = PQexec(conn, todo);
285
286         /* check and deal with errors */
287         if (!res || PQresultStatus(res) > 2)
288         {
289                 error_number = PQresultStatus(res);
290                 fprintf(stderr, "There was an error in the SQL command:\n%s\n", todo);
291                 sql_exec_error(error_number);
292                 fprintf(stderr, "PQerrorMessage = %s\n", PQerrorMessage(conn));
293
294                 PQclear(res);
295                 PQfinish(conn);
296                 exit(-1);
297         }
298
299         /* get the number of fields */
300         numbfields = PQntuples(res);
301
302         /* if we only expect 1 and there mode than,  return -2 */
303         if (match == 1 && numbfields > 1)
304                 return -2;
305
306         /* return -1 if there aren't any returns */
307         if (match == 1 && numbfields < 1)
308                 return -1;
309
310         /* for each row,  dump the information */
311         for (i = 0; i < numbfields; i++)
312         {
313                 len = strlen(PQgetvalue(res, i, 0));
314
315                 fprintf(stdout, "%-6s = %s\n", PQgetvalue(res, i, 0), PQgetvalue(res, i, 1));
316         }
317
318         /* clean the PGconn once done */
319         PQclear(res);
320
321         return 0;
322 }
323
324 /* dump all databases known by the system table */
325 void
326 sql_exec_dumpdb(PGconn *conn)
327 {
328         char            todo[1024];
329
330         /* get the oid and database name from the system pg_database table */
331         sprintf(todo, "select oid,datname from pg_database");
332
333         sql_exec(conn, todo, 0);
334 }
335
336 /* display all tables in whatever db we are connected to.  don't display the
337    system tables by default */
338 void
339 sql_exec_dumptable(PGconn *conn, int systables)
340 {
341         char            todo[1024];
342
343         /* don't exclude the systables if this is set */
344         if (systables == 1)
345                 sprintf(todo, "select relfilenode,relname from pg_class order by relname");
346         else
347                 sprintf(todo, "select relfilenode,relname from pg_class where relname not like 'pg_%%' order by relname");
348
349         sql_exec(conn, todo, 0);
350 }
351
352 /* display the oid for a given tablename for whatever db we are connected
353    to.  do we want to allow %bar% in the search?  Not now. */
354 void
355 sql_exec_searchtable(PGconn *conn, const char *tablename)
356 {
357         int                     returnvalue;
358         char            todo[1024];
359
360         /* get the oid and tablename where the name matches tablename */
361         sprintf(todo, "select relfilenode,relname from pg_class where relname = '%s'", tablename);
362
363         returnvalue = sql_exec(conn, todo, 1);
364
365         /* deal with the return errors */
366         if (returnvalue == -1)
367                 printf("No tables with that name found\n");
368
369         if (returnvalue == -2)
370                 printf("VERY scary:  more than one table with that name found!!\n");
371 }
372
373 /* same as above */
374 void
375 sql_exec_searchoid(PGconn *conn, int oid)
376 {
377         int                     returnvalue;
378         char            todo[1024];
379
380         sprintf(todo, "select relfilenode,relname from pg_class where oid = %i", oid);
381
382         returnvalue = sql_exec(conn, todo, 1);
383
384         if (returnvalue == -1)
385                 printf("No tables with that oid found\n");
386
387         if (returnvalue == -2)
388                 printf("VERY scary:  more than one table with that oid found!!\n");
389 }
390
391 int
392 main(int argc, char **argv)
393 {
394         struct options *my_opts;
395         PGconn     *pgconn;
396
397         my_opts = (struct options *) malloc(sizeof(struct options));
398
399         /* parse the opts */
400         get_opts(argc, argv, my_opts);
401
402         /* display all the tables in the database */
403         if (my_opts->getdatabase & my_opts->gettable)
404         {
405                 printf("Oid of table %s from database \"%s\":\n", my_opts->_tbname, my_opts->_dbname);
406                 printf("_______________________________\n");
407
408                 pgconn = sql_conn(my_opts->_dbname, my_opts);
409                 sql_exec_searchtable(pgconn, my_opts->_tbname);
410                 PQfinish(pgconn);
411
412                 exit(1);
413         }
414
415         /* search for the tablename of the given OID */
416         if (my_opts->getdatabase & my_opts->getoid)
417         {
418                 printf("Tablename of oid %i from database \"%s\":\n", my_opts->_oid, my_opts->_dbname);
419                 printf("---------------------------------\n");
420
421                 pgconn = sql_conn(my_opts->_dbname, my_opts);
422                 sql_exec_searchoid(pgconn, my_opts->_oid);
423                 PQfinish(pgconn);
424
425                 exit(1);
426         }
427
428         /* search for the oid for the given tablename */
429         if (my_opts->getdatabase)
430         {
431                 printf("All tables from database \"%s\":\n", my_opts->_dbname);
432                 printf("---------------------------------\n");
433
434                 pgconn = sql_conn(my_opts->_dbname, my_opts);
435                 sql_exec_dumptable(pgconn, my_opts->systables);
436                 PQfinish(pgconn);
437
438                 exit(1);
439         }
440
441         /* display all the databases for the server we are connected to.. */
442         printf("All databases:\n");
443         printf("---------------------------------\n");
444
445         pgconn = sql_conn("template1", my_opts);
446         sql_exec_dumpdb(pgconn);
447         PQfinish(pgconn);
448
449         exit(0);
450 }