/*
 * NAME
 *      pg_procs()   - get functions
 *
 * FILES
 *      pg_procs.c
 *
 * BUGS & HACKS
 *      prolang:  Need all the codes for this. Down below it outputs ??? twice
 *                for unrecognized languages.
 * AUTHOR
 *      J.T. Anderson, jean@gso.saic.com
 */

#ifndef lint
static char SccsId[] = "@(#)pg_procs.c	5.7 8/12/93";
#endif

#include "pg_schema.h"
#include "dd_queries.h"

#ifndef DEC
#include "assert.h"
#endif

extern dbConstr   *constr;
extern char       *strtok();

dbStatus
pg_procs(dbconn, obj_name, fp)
dbConn   *dbconn;
char     *obj_name;
FILE     *fp;
{
     char      *pg_type = "FUNCTIONS";
     char      *routine = "pg_procs";
     char      query[300];
     int       i, j, tuples, str_length, arr_length, is_null;
     short     postgres_id;

     dbObj     *result = NULL;
     void      *tuple = NULL;

     char      *proname, *return_type, *comment;
     int       *prolang;
     long      *prorettype;

     char      dbtype_s[GDI_MAX_TYPE+1];
     int       proargtypes, **arg_array;
     pgType    dbtype;

     int       status;

      /*  Find out the postgres id */
     strcpy(query, 
         "retrieve (pg_user.usesysid) where pg_user.usename=\"postgres\"");

#ifndef DEC
     assert( strlen(query) < sizeof(query) );
#endif

     if(gdi_submit(dbconn, query, GDI_FETCH_ALL, constr, &result)
          != GDI_SUCCESS)
     {    result = gdi_obj_destroy (result);
          return(GDI_FAILURE);
     }

     if ((tuple = gdi_obj_tuple_retrieve (result, 0)) == NULL) 
     {    fprintf(fp, "\n%s: gdi_obj_tuple_retrieve failed\n", routine);
          result = gdi_obj_destroy(result);
          return(GDI_FAILURE);
     }

     /* Column 0: usesysid           */
     if( (postgres_id = * (short *) gdi_obj_get_data (result, 0, tuple,
          &is_null, &str_length, &arr_length)) == NULL)
     {    fprintf(stderr, "%s: could not get postgres usesysid\n", routine);
          result = gdi_obj_destroy(result);
          return(GDI_FAILURE);
     }
     result = gdi_obj_destroy(result);

     if( (strlen(obj_name) == 0) || !strcmp(obj_name, "user") )
          sprintf (query, "%s where p.proowner != %d::oid", ALL_FUNCTIONS,
		postgres_id);
     else if(!strcmp(obj_name, "sys"))     
          sprintf (query, "%s where p.proowner = %d::oid", ALL_FUNCTIONS,
		postgres_id);
     else
          sprintf(query, "%s where p.proname =\"%s\"", ALL_FUNCTIONS, obj_name);

#ifndef DEC
     assert( strlen(query) < sizeof(query) );
#endif

     if(gdi_submit(dbconn, query, GDI_FETCH_ALL, constr, &result)
          != GDI_SUCCESS)
     {    result = gdi_obj_destroy (result);
          return(GDI_FAILURE);
     }

     tuples=GDI_OBJ_NUM_TUPLES(result);
     if(tuples == 0 )     
     {    if( (strlen(obj_name) == 0) || !strcmp(obj_name, "user") )
               fprintf(fp, "No user functions found.\n");
          else
               fprintf(fp, "Could not find function '%s' in database '%s'.\n",
                    obj_name, GDI_DATABASE(dbconn));

          result = gdi_obj_destroy(result);
          return(GDI_SUCCESS);
     }

     if (GDI_OBJ_NUM_COLUMNS(result) != 8)
     {    fprintf(fp, "%s: expected 8 columns but got %d\n",
               routine, GDI_OBJ_NUM_COLUMNS(result));
          fprintf(fp, "%s: did somebody change the query?\n", routine);
          result = gdi_obj_destroy(result);
          return(GDI_FAILURE);
     }

     print_header(fp, pg_type); 

     for(i=0; i < tuples; i++)
     {
          if ((tuple = gdi_obj_tuple_retrieve (result, i)) == NULL) 
          {    fprintf(fp, "\n%s: gdi_obj_tuple_retrieve failed\n", routine);
               return(GDI_FAILURE);
          }

          /* Column 0: proname           */
          if( (proname = (char *) gdi_obj_get_data (result, 0, tuple,
               &is_null, &str_length, &arr_length)) == NULL)
          {    fprintf(stderr, "%s: could not get proname\n", routine);
               result = gdi_obj_destroy(result);
               return(GDI_FAILURE);
          }

          /* Column 6: comment           */
          if( (comment = (char *) gdi_obj_get_data (result, 6, tuple,
               &is_null, &str_length, &arr_length)) == NULL)
          {    fprintf(stderr, "%s: could not get comment\n", routine);
               result = gdi_obj_destroy(result);
               return(GDI_FAILURE);
          }

          fprintf(fp, "define function %s\t", proname);
          if (is_null == 0)
               fprintf(fp, "/* %.*s */", COMMENT_SIZE, comment);
          fprintf(fp, "\n   ");

          /* Column 1: prolang           */
          if( (prolang = (int *) gdi_obj_get_data (result, 1, tuple,
               &is_null, &str_length, &arr_length)) == NULL)
          {    fprintf(stderr, "%s: could not get prolang\n", routine);
               result = gdi_obj_destroy(result);
               return(GDI_FAILURE);
          }

          fprintf(fp, "(language=");
          if(*prolang == 13)
               fprintf(fp, "\"c\",");
          else if(*prolang == 14)
               fprintf(fp, "\"postquel\",");
          else
               fprintf(fp, "\"??? (prolang=%d)\"", *prolang);
          
          /* Column 2: character decoding of prorettype --> return_type  */
          if( (return_type = (char *) gdi_obj_get_data (result, 2, tuple,
               &is_null, &str_length, &arr_length)) == NULL)
          {    fprintf(stderr, "%s: could not get return_type\n", routine);
               result = gdi_obj_destroy(result);
               return(GDI_FAILURE);
          }

          if(is_null == 0)
               fprintf(fp, " returntype=%s) ", return_type);
          else
          {
               if( (prorettype = (long *) gdi_obj_get_data (result, 7, tuple,
                    &is_null, &str_length, &arr_length)) == NULL)
               {    fprintf(stderr, "%s: could not get prorettype\n", routine);
                    result = gdi_obj_destroy(result);
                    return(GDI_FAILURE);
               }

               fprintf(fp, " returntype=(??? prorettype=%d)) ", *prorettype);
          }

          fprintf(fp, "arg is (");
          
          /* Column 3: proargtypes (oid8)  */
          if( (arg_array = (int **) gdi_obj_get_data (result, 3, tuple,
               &is_null, &str_length, &arr_length)) == NULL)
          {    fprintf(stderr, "%s: could not get proargtypes\n", routine);
               result = gdi_obj_destroy(result);
               return(GDI_FAILURE);
          }

          for (j=0, proargtypes = -1 ; (j < arr_length) && (proargtypes != 0); j++)
          {    
               proargtypes = (* arg_array)[j];
               dbtype = (pgType) proargtypes;
               
               if (proargtypes > 0)
               {    
                    status = pg_builtin_dbtype_s (dbconn, &dbtype, dbtype_s);

                    if ( (j > 0) && (j < 6) )
                         fprintf(fp, ", ");

                    if(status == GDI_FAILURE)
                         fprintf(fp, "??? proargtypes[%d] = %d", j+1, dbtype);
                    else
                         fprintf(fp, "%s", dbtype_s);
               }
          }

          if(*prolang == 13)        /* Column 5: probin for C */
          {
               fprintf(fp, ")\n   as \"%s\" \n\\g\n\n", 
                    (char *) gdi_obj_get_data (result, 5, tuple,
                         &is_null, &str_length, &arr_length));
          }
          else if (*prolang == 14)  /* Column 4: prosrc for Postquel */
          {
               fprintf(fp, ")\n   as \"%s\" \n\\g\n\n", 
                    (char *) gdi_obj_get_data (result, 4, tuple,
                         &is_null, &str_length, &arr_length));
          }
          else
               fprintf(fp, ")\n   as \"??? prolang=%d\" \n\\g\n\n", *prolang);
     }

     result = gdi_obj_destroy(result);
     return(GDI_SUCCESS);
}
