/*
 * NAME
 *     pg_schema
 *
 * USAGE
 *      pg_schema [-d database] [-c user|sys|class_name] 
 *	          [-i user|sys|index_name] [-f user|sys|func_name] 
 *                [-o output_file] [-h host] [-g 0|1|2] [-t] 
 *
 * ARGUMENTS
 *     -d   POSTGRES database name
 *     -h   POSTGRES host name
 *     -c   Name of a class to describe; "user" gets user classes,
 *          "sys" gets system catalogs.
 *     -i   Name of an index to describe; "user" gets user indexes,
 *          "sys" gets system catalogs.
 *     -f   Name of a stored function to describe; "user" gets user 
 *          functions, "sys" gets system functions.
 *
 *     -o   Output filename. If not set, output is sent to the screen.
 *
 *     -g   gdi degub level: 0 (off) by default
 *          1 = GDI_DEBUG_ON
 *          2 = GDI_DEBUG_VERBOSE
 *
 *     -t   turns PQtrace on
 *
 *     If 'c', 'i', and 'f' are NOT set, gets all user classes, indexes, and
 *     functions.
 *
 * DESCRIPTION
 *      Generates create statements from the POSTGRES system catalogs.
 *
 * AUTHOR
 *     Jean T. Anderson
 */
#ifndef lint
static char     SccsId[] = "%W% %G%";
#endif

#include "pg_schema.h"

FILE      *fp, *fopen();

#ifndef DEC
FILE	*fclose();
#endif

extern    void perror();
extern    int getopt();

Proto     (static void,     pg_cleanup,     (dbConn *dbconn));
dbConstr  *constr;

char      filename[ _POSIX_PATH_MAX + 1 ];

#define USAGE1\
"Usage:\tpg_schema\t[-d database] [-c user|sys|class_name] [-i user|sys|index_name]\\"
#define USAGE2\
"\t\t[-f user|sys|func_name] [-o output_filename] [-h host] [-g 0|1|2] [-t] "

extern char     *optarg;

/****************************************************************************/
/*  main                                                                    */
/****************************************************************************/
int
main(argc, argv)
int        argc;
char      **argv;
{
     char    *vendor="postgres";
     char    database[GDI_DBNAME_SIZE +1], pg_host[80];
     char    c_name[GDI_TABLENAME_SIZE + 1],
             i_name[GDI_TABLENAME_SIZE + 1],
             f_name[GDI_TABLENAME_SIZE + 1];

     int     c, c_flag=0, i_flag=0, f_flag=0;

     dbConn  *dbconn = NULL;      /* GDI database connector */
     int     debug = 0; 
     int     trace = 0;    /* GDI debug and trace */

     /* GDI_TURBO is the only constructor that does POSTGRES array types */
     constr = &GDI_TURBO;

     /*=====================================================*
      *========= Get command line arguments ================*
      *=====================================================*/

        c_name[0] = '\0';
        i_name[0] = '\0';
        f_name[0] = '\0';
        filename[0] = '\0';
        bzero(pg_host, sizeof(pg_host));
        bzero(database, sizeof(database));

     while ((c = getopt(argc, argv, "c:d:f:g:h:i:o:t")) != EOF)
     {
          switch(c)
          {
          case 'c':
               c_flag++;
               (void) strncpy (c_name, optarg, sizeof(c_name) - 1);
               c_name[sizeof(c_name) - 1] = '\0';
               break;
          case 'd':
               (void) strncpy (database, optarg, sizeof(database) - 1);
               database[sizeof(database) - 1] = '\0';
               break;
          case 'g':
               debug = atoi (optarg);
               break;
          case 'i':
               i_flag++;
               (void) strncpy (i_name, optarg, sizeof(i_name) - 1);
               i_name[sizeof(i_name) - 1] = '\0';
               break;
          case 'f':
               f_flag++;
               (void) strncpy (f_name, optarg, sizeof(f_name) - 1);
               f_name[sizeof(f_name) - 1] = '\0';
               break;
          case 'o':
               (void) strncpy (filename, optarg, sizeof(filename) - 1);
               filename[sizeof(filename) - 1] = '\0';
               break;
          case 'h':
               (void) strncpy (pg_host, optarg, sizeof(pg_host) - 1);
               pg_host[sizeof(pg_host) - 1] = '\0';
               break;
          case 't':
               trace++;
               break;
          default:
               fprintf(stderr, "%s\n", USAGE1);
               fprintf(stderr, "%s\n", USAGE2);
               exit(1);
          }
     }

     /* If no flags are set, output all user objects */

     if( !c_flag && !i_flag && !f_flag )
     {    c_flag++;
          i_flag++;
          f_flag++;
     }

     /* ==============
      * Initialize GDI
      * ==============
      */

     gdi_init(argv[0]);

     /* ====================
      * Connect to Database
      * ====================
      */
     (void) gdi_error_init(NULL, debug, GDI_WARNING, 
          GDI_NOT_USED, GDI_NOT_USED);

     if ((dbconn = gdi_open(vendor, NULL, NULL, database, pg_host, NULL))
          == (dbConn *)NULL )
     {
          fprintf (stderr, "Connect failed: %s\n", 
                    GDI_ERROR_MSG( (dbConn *)NULL) );
          exit (GDI_FAILURE);
     }

     /* ====================
      * Set Debug & Trace
      * ====================
      */
     (void) gdi_error_init(dbconn, debug, GDI_WARNING, 
          GDI_NOT_USED, GDI_NOT_USED);

     if(trace)
          gdi_trace(dbconn, TRUE, "");

     if (pg_init(dbconn) == GDI_FAILURE)
     {
          fprintf (stderr, "pg_init failed: %s\n", GDI_ERROR_MSG(dbconn));
          exit (GDI_FAILURE);
     }

     /* ====================
      * Open output file
      * ====================
      */
     if(filename[0] == '\0')
          fp=stdout;
     else 
     {    fp=fopen(filename, "w");
          if(fp == NULL)
          {    perror (argv[0]);
               (void) gdi_close(dbconn);
               exit(GDI_FAILURE);
          }
     }

     /* ====================
      * Output Classes 
      * ====================
      */

     if(c_flag)
     {
          if( (pg_class(dbconn, c_name, fp)) != GDI_SUCCESS)
          {
               fprintf (stderr, "pg_class failed: %s\n", 
                    GDI_ERROR_MSG(dbconn));
               pg_cleanup(dbconn);
               exit(GDI_FAILURE);
          }
     }

     /* ====================
      * Output Indexes 
      * ====================
      */
     if (i_flag)
     {
          if ( (pg_indexes(dbconn, i_name, fp)) != GDI_SUCCESS)
          {
               fprintf (stderr, "pg_indexes failed: %s\n", 
                    GDI_ERROR_MSG(dbconn));
               pg_cleanup(dbconn);
               exit(GDI_FAILURE);
          }
     }

     /* ====================
      * Output Functions 
      * ====================
      */
     if (f_flag)
     {
          if ( (pg_procs(dbconn, f_name, fp)) != GDI_SUCCESS)
          {
               fprintf (stderr, "pg_procs failed: %s\n", 
                    GDI_ERROR_MSG(dbconn));
               pg_cleanup(dbconn);
               exit(GDI_FAILURE);
          }
     }

     /* ====================
      * Close
      * ====================
      */
     pg_cleanup(dbconn);
     exit(GDI_SUCCESS);
}


static
void
pg_cleanup(dbconn)
dbConn     *dbconn;
{
     if(gdi_close(dbconn) != GDI_SUCCESS)
     {
          fprintf (stderr, "gdi_close failed: %s\n", 
               GDI_ERROR_MSG(dbconn));
          exit(GDI_FAILURE);
     }

     if(strlen(filename) > 0)
          fclose(filename);
     return;
}
