
 
/***************************************************************************
 *                                                                         *
 * Alberi:  Graphical Language Interface for POSTGRES                      *
 *                                                                         *
 * Copyright (c) 1992, 1993 The University of Georgia Research             *
 *                          Foundation, Inc.                               *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 * Designer and Programmer:  Ruben Robles                                  *
 * Email:  ruben@pollux.cs.uga.edu or rubenr3@aol.com or                   *
 *         rubenr3@psi.com@aol.com                                         *
 *                                                                         *
 * Modified by:		K.J. Kochut                                        *
 *			Department of Computer Science                     *
 *			University of Georgia                              *
 *			Athens, GA 30602                                   *
 *                                                                         *
 * Send comments/fixes/improvements/modifications to:                      *
 *                                                                         *
 *                     kochut@cs.uga.edu                                   *
 *                                                                         *
 ***************************************************************************/



/* 
 * ***********  POSTGRES code was used and modified here 
 */



#include <sys/param.h>
#include <sys/types.h>
#include <xview/xview.h>
#include <xview/frame.h>
#include <xview/panel.h>
#include <xview/textsw.h>
#include <xview/xv_xrect.h>

#include <utils/log.h>

#include "first_ui.h"
#include "command_log_ui.h"
#include "q_process.h"

extern char *PQhost;
extern char *PQport;
extern char *PQtty;
extern char *PQoption;
extern char  PQdatabase[];
extern int   PQportset;
extern int   PQxactid;

extern bool TerseOutput, PrintAttNames, Silent, Verbose;
extern command_log_pop_objects	*command_log_pop;

char *
clean_query (raw_query) 
char *raw_query;
{
  char query[8096];
  char *answer;
  int index1, index2, comment;

  index2 = 0;
  query[0] = 0;
  comment = 0;
   
  for (index1 = 0;
       isspace(raw_query[index1]) && raw_query[index1] != 0;
       index1++)
    continue; 			/* skip beg. white sp */
  
  while ( raw_query[index1] != 0 ) {
    if ( !comment ) {
      switch(raw_query[index1]) {
      case '\\':
	{
	  if (raw_query[index1+1] != 0) {
	    query[index2++] = ' ';
	    index1++;
	    index1++;
	  } else index1++;
	}
	break;
      case '\n':
	{
	  query[index2++] = ' ';
	  index1++;
	}
	break;
      case '/':
	{
	  if (raw_query[index1+1] != 0) {
	    if (raw_query[index1+1] == '*' ) {
	      index1++;
	      index1++;
	      comment = 1;
	    } else {
	      query[index2++] = raw_query[index1++];
	      query[index2++] = raw_query[index1++];
	    }
	  }
	}
	break;
      default:
	query[index2++] = raw_query[index1++];
	break;
      }
    } else {
      if (raw_query[index1] == '*') {
	if (raw_query[index1+1] != 0) {
	  if (raw_query[index1+1] == '/') {
	    index1++;
	    index1++;
	    comment = 0;
	  } else {
	    fprintf(stderr, "Query ended while in a unfinished comment\n");
	  }
	}
      } else index1++;
    }
  }
  query[index2] = 0;
  if (query[0] == 0) {
    query[0] = ' ';
    query[1] = 0;
  }
  answer = (char *) malloc(strlen(query) + 1);
  if (answer != NULL) 
    strcpy(answer, query);
  return answer;
}


/*
 * print_tuples()
 *
 * This is the routine that prints out the tuples that
 * are returned from the backend.
 * Right now all columns are of fixed length.
 * 
 */

void
print_tuples (pname, ip)
     char *pname;
     first_window1_objects  *ip;
{

    PortalBuffer *p;
    int j,k,g,m,n,t,x;
    int temp, temp1;
    char *tborder;
    char buf[8192];
    char **strings;
    int *slen;
    
    /* Now to examine all tuples fetched. */
    p = PQparray(pname);
    g = PQngroups (p);
    t = 0;
    temp = 0;

    for (k =0; k < g-1; k++) {
        temp += PQntuplesGroup(p,k);
    }

    /* Now to print out the attribute names 
     *
     * XXX Cheap Hack. For now, we see only the last group
     * of tuples.  This is clearly not the right
     * way to do things !!
     */

    n = PQntuplesGroup(p,g-1);  /* zero based index.  */
    m = PQnfieldsGroup(p,g-1);
    strings = (char **)calloc(m,sizeof(char*));
    slen = (int *)calloc(m,sizeof(int *));
    
    if ( m > 0 ) {  /* only print tuples with at least 1 field.  */

        if (!TerseOutput) {
            temp1 = (int) m * 14;
            tborder = malloc (temp1+1);
            for (x = 0; x <= temp1; x++) 
                tborder[x] = '-';
            tborder[x] = '\0';
            sprintf(buf,"%s\n",tborder); 
            textsw_insert(ip->textpane3, buf, strlen(buf));
        }

        for (x=0; x < m; x++) {
            if (PrintAttNames && !TerseOutput) {
                sprintf(buf,"| %-12.12s",PQfnameGroup(p,g-1,x));
                textsw_insert(ip->textpane3, buf, strlen(buf));
            }
            else if (PrintAttNames) {
                sprintf(buf," %-12.12s",PQfnameGroup(p,g-1,x));
                textsw_insert(ip->textpane3, buf, strlen(buf));
            }
        }

        if (PrintAttNames && !TerseOutput) {
            sprintf(buf, "|\n");
            textsw_insert(ip->textpane3, buf, strlen(buf));
            sprintf(buf,"%s\n",tborder);
            textsw_insert(ip->textpane3, buf, strlen(buf));
        }
        else if (PrintAttNames) {
            sprintf(buf, "\n");
            textsw_insert(ip->textpane3, buf, strlen(buf));
        }

        /* Print out the tuples */
        t += temp;

        for (x = 0; x < n; x++) {
            int maxlen;
            int wraps;
            int outlen;

            maxlen = 0;

            for(j = 0; j < m; j++) {

                char *stmp;

                stmp = (char *) PQgetvalue(p,t+x,j);
                if ( !stmp ) 
		  stmp = "(null)";
                strings[j] = (char *)malloc(strlen(stmp)+1);
                strcpy(strings[j],stmp);
                slen[j] = strlen(strings[j]);
                if (slen[j] > maxlen) maxlen = slen[j];
            }

            wraps = maxlen / 12 + ((maxlen % 12) > 0 ? 1 : 0);

            outlen = 0;

            for (k=0;k<wraps;k++) {
                for (j = 0; j < m; j++) {

                    if (!TerseOutput) {
                        if (outlen < slen[j]) {
                            sprintf(buf, "| %-12.12s", strings[j]+outlen);
                            textsw_insert(ip->textpane3,buf,14);
                        }
                        else {
                            sprintf(buf,"| %-12.12s"," ");
                            textsw_insert(ip->textpane3,buf,14);
                        }
                    }
                    else {
                        if (outlen < slen[j]) {
                            sprintf(buf, " %-12.12s", strings[j]+outlen);
                            textsw_insert(ip->textpane3, buf,13);
                        }
                        else {
                            sprintf(buf," %-12.12s"," ");
                            textsw_insert(ip->textpane3,buf,13);
                        }
                    }
                }
                outlen +=12;

                if (!TerseOutput) {
                    sprintf (buf, "|\n");
                    textsw_insert(ip->textpane3, buf, 2);
                }
                else {
                    sprintf(buf, "\n");
                    textsw_insert(ip->textpane3, buf, 1);
                }
            }

            if (!TerseOutput) {
                sprintf(buf,"%s\n",tborder);
                textsw_insert(ip->textpane3, buf, strlen(buf));
            }
            for (j=0; j<m; j++) free(strings[j]);
        }
        if (!TerseOutput) free(tborder);
    }
    free(strings);
    free(slen);
}

int
handle_execution(query, ip)
     char *query;
     first_window1_objects *ip;
{
    
  char *alberi_PQexec();
  bool done = false;
  bool entering = true;

  char *pstring1;
  char pstring[256], buffy[256];
  int nqueries = 0;
  int retval = 0;

  textsw_insert( command_log_pop->textpane1, query, strlen(query) );
  textsw_insert( command_log_pop->textpane1, "\n", 1 );

    /* ip = first_window1_objects_initialize(NULL, NULL); */
  while (!done) {

    if (entering) {
      pstring1 = alberi_PQexec(query); 
      entering = false;
    } 

    strcpy(pstring, pstring1);
        
        switch(pstring[0]) {
        case 'A':
        case 'P':
            
            print_tuples( &(pstring[1]), ip);
            PQclear(&(pstring[1]));
            /* xv_set(ip->window1, FRAME_LEFT_FOOTER, "No errors", NULL); */
            pstring1 = alberi_PQexec(" ");
            
            nqueries++;
            break;
            
        case 'E':		/* never really used (KJK) */
            {
	      xv_set(ip->window1,
		     FRAME_LEFT_FOOTER, "Errors... big ones, see console", 
		     NULL);
            
	      elog (FATAL,&(pstring[1]));
	      retval = 1;
            }
            break;
            
        case 'C':
	    if (!Silent) {
                sprintf(buffy,"%s",&(pstring[1]));
		textsw_insert(ip->textpane3, buffy, strlen(buffy));
            }
            if (!Verbose && !Silent) {
                 sprintf(buffy,"\n");
		 textsw_insert(ip->textpane3, buffy, strlen(buffy));
            }
            pstring1 = alberi_PQexec(" ");
            nqueries++;
            break;
            
        case 'I':
            PQFlushI(nqueries - 1);
            done = true;
            break;
            
        case 'R':
            done = true;
            
            sprintf(buffy, "\n%s\n", &(pstring[1]));
	    print_error( buffy );
	    retval = 1;
            break;

        case 'B':
            {
                char s[100];

                s[0] = ' ';

		if (!Silent) {
                     sprintf(buffy, "Copy command returns...\n");
		     textsw_insert(ip->textpane3, buffy, strlen(buffy));
                }

                while (s[0] != '.')
                {
                    PQgetline(s, 100);
		    if (s[0] != '.')  {
		      sprintf(buffy, "%s\n", s); 
		      textsw_insert(ip->textpane3, buffy, strlen(buffy));
		    }
		}
            }
	    PQendcopy();
	    done = 1;
	    break;
	case 'D':
	    {
                char s[100];

                s[0] = ' ';

		/* eat inevitable newline still in input buffer */

		while (getchar() != '\n')
		    continue;

		if (!Silent) {
                     sprintf(buffy, "Enter info followed by a newline\n");
		     textsw_insert(ip->textpane3, buffy, strlen(buffy));
                     sprintf(buffy, "End with a dot on a line by itself.\n");
		     textsw_insert(ip->textpane3, buffy, strlen(buffy));
		}

		fflush(stdin);
                while (s[0] != '.')
                {
                     sprintf(buffy, ">> ");
		    textsw_insert(ip->textpane3, buffy, strlen(buffy));
		    gets(s);
		    PQputline(s);
		    PQputline("\n");
		}
            }
	    PQendcopy();
            done = true;
	    break;
        default:
             textsw_insert(ip->textpane3,"unknown type\n", 13);
          }
  }
  return(retval);
}
