/* dynamic SQL test program
 *
 * Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
 *
 * $PostgreSQL: pgsql/src/interfaces/ecpg/test/dyntest.pgc,v 1.11 2005/06/30 07:08:59 neilc Exp $
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

exec sql include sql3types;
exec sql include sqlca;

static void error(void)
{  printf("#%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
   exit(1);
}

int main(int argc,char **argv)
{ exec sql begin declare section;
  int COUNT;
  int INTVAR;
  int INDEX;
  int INDICATOR;
  bool BOOLVAR;
  int TYPE,LENGTH,OCTET_LENGTH,PRECISION,SCALE,NULLABLE,RETURNED_OCTET_LENGTH;
  int DATETIME_INTERVAL_CODE;
  char NAME[120];
  char STRINGVAR[1024];
  float FLOATVAR;
  double DOUBLEVAR;
  char QUERY[1024];
  char DB[1024];
  exec sql end declare section;
  int done=0;
  FILE *dbgs;
  
  if ((dbgs = fopen("log", "w")) != NULL)
                ECPGdebug(1, dbgs);

  snprintf(QUERY,sizeof QUERY,"select * from %s",argc>1 && argv[1][0]?argv[1]:"pg_tables");

  exec sql whenever sqlerror do error();
  
  exec sql allocate descriptor MYDESC;

  strncpy(DB,argc>2?argv[2]:"mm",sizeof DB);
  exec sql connect to :DB;
  
  exec sql prepare MYQUERY from :QUERY;
  exec sql declare MYCURS cursor for MYQUERY;
  
  exec sql open MYCURS;
  
  while (1)
  {  exec sql fetch in MYCURS into sql descriptor MYDESC;
     
     if (sqlca.sqlcode) break;
     
     exec sql get descriptor MYDESC :COUNT = count;
     if (!done) 
     {  printf("%d Columns\n",COUNT);
        for (INDEX=1;INDEX<=COUNT;++INDEX)
        {	exec sql get descriptor MYDESC value :INDEX
        		:TYPE = type,
        		:LENGTH = length, :OCTET_LENGTH=octet_length,
        		:PRECISION = precision, :SCALE=scale,
        		:NULLABLE=nullable, :NAME=name,
        		:RETURNED_OCTET_LENGTH=returned_octet_length;
			printf("%s ",NAME);
        	switch (TYPE)
        	{  case SQL3_BOOLEAN: 
        			printf("bool ");
        			break;
        	   case SQL3_NUMERIC:
        	   		printf("numeric(%d,%d) ",PRECISION,SCALE);
        	        break;
        	   case SQL3_DECIMAL:
        	   		printf("decimal(%d,%d) ",PRECISION,SCALE);
        	        break;
        	   case SQL3_INTEGER: 
        	   		printf("integer ");
        	   		break;
        	   case SQL3_SMALLINT:
        	   		printf("smallint ");
        	        break;
        	   case SQL3_FLOAT:
        	   		printf("float(%d,%d) ",PRECISION,SCALE);
        	        break;
        	   case SQL3_REAL:
        	   		printf("real ");
        	        break;
        	   case SQL3_DOUBLE_PRECISION:
        	   		printf("double precision ");
        	        break;
        	   case SQL3_DATE_TIME_TIMESTAMP:
        	   		exec sql get descriptor MYDESC value :INDEX 
        	   		:DATETIME_INTERVAL_CODE=datetime_interval_code;
        	   		switch(DATETIME_INTERVAL_CODE)
        	   		{	case SQL3_DDT_DATE: 
        	   				printf("date "); break;
        	   			case SQL3_DDT_TIME: 
        	   				printf("time "); break;
        	   			case SQL3_DDT_TIMESTAMP: 
        	   				printf("timestamp "); break;
        	   			case SQL3_DDT_TIME_WITH_TIME_ZONE: 
        	   				printf("time with time zone "); break;
        	   			case SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE: 
        	   				printf("timestamp with time zone "); break;
        	   		}
        	        break;
        	   case SQL3_INTERVAL:
        	   		printf("interval ");
        	        break;
        	   case SQL3_CHARACTER:
        	        if (LENGTH>0) printf("char(%d) ",LENGTH);
        	        else printf("char(?) ");
        	        break;
        	   case SQL3_CHARACTER_VARYING:
        	        if (LENGTH>0) printf("varchar(%d) ",LENGTH);
        	        else printf("varchar() ");
        	        break;
        	   default:
        	        if (TYPE<0) printf("<OID %d> ",-TYPE);
        	        else printf("<SQL3 %d> ",TYPE);
        	        break;
        	}
        	if (!NULLABLE) printf("not null ");
        	if (OCTET_LENGTH>0) printf("[%d bytes]",OCTET_LENGTH);
        	putchar('\n');
        }
        putchar('\n');
        done=1;
     } 
     
     for (INDEX=1;INDEX<=COUNT;++INDEX)
     {  exec sql get descriptor MYDESC value :INDEX 
     		:TYPE = type, :SCALE=scale, :PRECISION = precision,
     		:INDICATOR=indicator;
     	if (INDICATOR==-1) printf("NULL");
        else switch (TYPE)
     	{	case SQL3_BOOLEAN: 
     	        exec sql get descriptor MYDESC value :INDEX :BOOLVAR=data;
     			printf(BOOLVAR?"true":"false");
     			break;
     	   	case SQL3_NUMERIC:
     	   	case SQL3_DECIMAL:
     	        if (SCALE==0) /* we might even print leading zeros "%0*d" */
     	        {  exec sql get descriptor MYDESC value :INDEX :INTVAR=data;
     	           printf("%*d",PRECISION,INTVAR);
     	        }
     	        else
     	        {  exec sql get descriptor MYDESC value :INDEX :FLOATVAR=data;
     	           printf("%*.*f",PRECISION+1,SCALE,FLOATVAR);
     	        }
     	        break;
     	   	case SQL3_INTEGER:
     	   	case SQL3_SMALLINT: 
     	        exec sql get descriptor MYDESC value :INDEX :INTVAR=data;
     	        printf("%d",INTVAR);
     	        break;
     	   	case SQL3_FLOAT:
     	   	case SQL3_REAL:
     	        exec sql get descriptor MYDESC value :INDEX :FLOATVAR=data;
     	        printf("%f",FLOATVAR);
     	        break;
     	   	case SQL3_DOUBLE_PRECISION:
     	        exec sql get descriptor MYDESC value :INDEX :DOUBLEVAR=data;
     	        printf("%f",DOUBLEVAR);
     	        break;
     	   	case SQL3_DATE_TIME_TIMESTAMP:
     	   	case SQL3_INTERVAL:
     	   	case SQL3_CHARACTER:
     	   	case SQL3_CHARACTER_VARYING:
     	   	default:
     	        exec sql get descriptor MYDESC value :INDEX :STRINGVAR=data;
     	        printf("'%s'",STRINGVAR);
     	        break;
     	}
     	putchar('|');
     }
     putchar('\n');
  }
  
  exec sql close MYCURS;
  
  exec sql deallocate descriptor MYDESC;

  if (dbgs != NULL)
       fclose(dbgs);

  return 0;
}
