///////////////////////////////////////////////////////////////////////////////
//                                                         
// cgwtest.c
// ---------
// Cego C wrapper test program
// 
// Design and Implementation by Bjoern Lemke               
//                                                         
// (C)opyright 2009 Bjoern Lemke                        
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; see the file COPYING.  If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
//
///////////////////////////////////////////////////////////////////////////////

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

#include "cgwrap.h"

void connect_test();
void create_test();
void drop_test();
void prepstmt1_test();
void prepstmt2_test();
void fetch_test();
void inout_test();
void blob_test();


char host[] = "localhost";
char tableset[] = "TS1";
char user[] = "lemke";
char passwd[] = "lemke";
char cgwlog[] = "cgwrap.log";
char prot[] = "serial";

char proccreatestmt[] = "create procedure checkInOut ( inVal in string(30), outVal out string(30) ) return int \
begin \
   insert into t1 values ( 1000, :inVal ); \
   :outVal = 'Out-Out'; \
   return 42; \
end;";
char tabcreatestmt[] = "create table t1 ( a int, b string(30));";
char procdropstmt[] = "drop procedure checkInOut;";
char tabdropstmt[] = "drop table t1;";


int main(int argc, char** argv) 
{

    if ( argc > 1 )
    {
	if ( strcmp (argv[1], "connect") == 0)
	{
	    connect_test();
	}
	else if ( strcmp (argv[1], "create") == 0)
	{
	    create_test();
	}
	else if ( strcmp (argv[1], "drop") == 0)
	{
	    drop_test();
	}
	else if ( strcmp (argv[1], "prepstmt1") == 0)
	{
	    prepstmt1_test();
	}
	else if ( strcmp (argv[1], "prepstmt2") == 0)
	{
	    prepstmt2_test();
	}
	else if ( strcmp (argv[1], "fetch") == 0)
	{
	    fetch_test();
	}
	else if ( strcmp (argv[1], "inout") == 0)
	{
	    inout_test();
	}
	else if ( strcmp (argv[1], "blob") == 0)
	{
	    blob_test();
	}
    }

}

void connect_test()
{

    CGDB *cgdb;
    
    printf("Connecting ...\n");
    
    if ( (cgdb = cego_connect(host, 2200, prot, tableset, user, passwd, cgwlog)) == NULL )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }

    cego_modlog("ALL", CG_LOG_DEBUG);

    printf("Connect ok\n");
    
    cego_disconnect(cgdb);
}

void create_test()
{

    CGDB *cgdb;
    
    printf("Connecting ...\n");
    
    if ( (cgdb = cego_connect(host, 2200, prot, tableset, user, passwd, cgwlog)) == NULL )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }

    cego_modlog("ALL", CG_LOG_DEBUG);
    
	
    printf("Executing query ...\n");
    if ( cego_query (cgdb, tabcreatestmt, 0) != 0 )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }
    printf("Query ok\n");

    if ( cego_query (cgdb, proccreatestmt, 0) != 0 )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }
    printf("Query ok\n");


    cego_disconnect(cgdb);
}

void drop_test()
{

    CGDB *cgdb;
    
    printf("Connecting ...\n");
    
    if ( (cgdb = cego_connect(host, 2200, prot, tableset, user, passwd, cgwlog)) == NULL )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }

    cego_modlog("ALL", CG_LOG_DEBUG);
	
    printf("Executing query ...\n");
    if ( cego_query (cgdb, tabdropstmt, 0) != 0 )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }
    printf("Query ok\n");

    if ( cego_query (cgdb, procdropstmt, 0) != 0 )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }
    printf("Query ok\n");


    cego_disconnect(cgdb);
}


void prepstmt1_test()
{

    CGDB *cgdb;
    
    printf("Connecting ...\n");
    
    if ( (cgdb = cego_connect(host, 2200, prot, tableset, user, passwd, cgwlog)) == NULL )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }
 
    printf("Prepare stmt ...\n");
    CGStmt *pStmt;
    pStmt = cego_prepare("insert into t1 values ( ? , ? );");

    int *pI = (int*)malloc(sizeof(int));
    *pI = 42;
    CGVal *pV1 = (CGVal*)malloc(sizeof(CGVal));
    pV1->type = CG_INT;
    pV1->len = sizeof(int);
    pV1->val = pI;
    
    char *s = (char*)malloc(20);
    strcpy(s, "This is a X"); 
    CGVal *pV2 = (CGVal*) malloc(sizeof(CGVal));
    
    pV2->type = CG_VARCHAR;
    pV2->len = strlen(s);
    pV2->val = s;
    
    printf("Bind stmt ...\n");
    cego_bind_in(pStmt, pV1, 1);
    cego_bind_in(pStmt, pV2, 2);
 
    printf("Execute stmt ...\n");
    if ( cego_execute(cgdb, pStmt, 0) != 0)
    {
	printf("Error : %s\n", cgerrmsg); 
    }
    printf("Prepared Stmt ok\n");

    cego_free_stmt(pStmt);

    cego_disconnect(cgdb);
}


void prepstmt2_test()
{

    CGDB *cgdb;
    
    printf("Connecting ...\n");
    
    if ( (cgdb = cego_connect(host, 2200, prot, tableset, user, passwd, cgwlog)) == NULL )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }
 
    printf("Prepare stmt ...\n");
    CGStmt *pStmt;
    pStmt = cego_prepare("select a, b from t1;");


    printf("Creating fetch handle ...\n");
    CGFetch* cgfetch = cego_allocate_fetch();

    printf("Making query ...\n");
    if ( cego_execute(cgdb, pStmt, cgfetch) != 0 )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }
    
    printf("Size=%d\n", cego_num_col(cgfetch));
    
    CGVal cgval[2];
    cgval[0].val=0;
    cgval[1].val=0;

    int colnum;
    colnum = cego_fetch (cgfetch, cgval, 2);
    cego_abort(cgfetch);
    cego_disconnect(cgdb);


    while ( ( colnum = cego_fetch (cgfetch, cgval, 2)) > 0 )
    {

	int i=0;
	while ( i < colnum )
	{
	    printf("Col %d\n", i);
	    if ( cgval[i].type == CG_VARCHAR )
		printf("%s ", (char*)cgval[i].val);
	    else if ( cgval[i].type == CG_INT )
		printf("%d ", *(int*)cgval[i].val);
	    i++;
	}
	printf("\n");

	cego_abort(cgfetch);
	break;
    }

    printf("Fetch ok\n");
    cego_free_fetch(cgfetch);
    
    printf("Prepared Stmt ok\n");

    cego_disconnect(cgdb);
}


void fetch_test()
{

    CGDB *cgdb;
    
    printf("Connecting ...\n");
    
    if ( (cgdb = cego_connect(host, 2200, prot, tableset, user, passwd, cgwlog)) == NULL )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }

    printf("Creating fetch handle ...\n");
    CGFetch* cgfetch = cego_allocate_fetch();

    printf("Making query ...\n");
    if ( cego_query(cgdb, "select a, b from t1;", cgfetch) != 0 )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }
    
    printf("Size=%d\n", cego_num_col(cgfetch));
    
    CGVal cgval[2];
    cgval[0].val=0;
    cgval[1].val=0;

    int colnum;
    while ( ( colnum = cego_fetch (cgfetch, cgval, 2)) > 0 )
    {

	int i=0;
	while ( i < colnum )
	{
	    printf("Col %d, Name %s\n", i, cego_getcol(cgfetch, i));
	    if ( cgval[i].type == CG_VARCHAR )
		printf("%s ", (char*)cgval[i].val);
	    else if ( cgval[i].type == CG_INT )
		printf("%d ", *(int*)cgval[i].val);
	    i++;
	}
	printf("\n");
    }

    printf("Fetch ok\n");

    cego_free_fetch(cgfetch);    
    cego_disconnect(cgdb);
}


void inout_test()
{

    CGDB *cgdb;
    
    printf("Connecting ...\n");
    
    if ( (cgdb = cego_connect(host, 2200, prot, tableset, user, passwd, cgwlog)) == NULL )
    {
        printf("Error : %s\n", cgerrmsg);
        exit(1);
    }

    printf("Prepare stmt ...\n");
    CGStmt *pStmt;
    pStmt = cego_prepare("? = call checkInOut( ? , ? );");

    CGVal v1;
    v1.val = 0;
        
    char s[20] = "This is XXXX"; 
    CGVal v2;
    
    v2.type = CG_VARCHAR;
    v2.len = strlen(s);
    v2.val = s;

    CGVal v3;
    v3.val = 0;
    
    printf("Bind stmt ...\n");
    cego_bind_out(pStmt, &v1, 1);
    cego_bind_in(pStmt, &v2, 2);
    cego_bind_out(pStmt, &v3, 3);
 
    printf("Execute stmt ...\n");
    if ( cego_execute(cgdb, pStmt, 0) != 0)
    {
        printf("Error : %s\n", cgerrmsg); 
    }

    printf("P1 = %d\n", *(int*)v1.val);
    printf("P2 = %s\n", (char*)v2.val);
    printf("P3 = %s\n", (char*)v3.val);
    
    printf("InOut ok\n");

    cego_disconnect(cgdb);
}

void blob_test()
{

    CGDB *cgdb;
    
    printf("Connecting ...\n");
    
    if ( (cgdb = cego_connect(host, 2200, prot, tableset, user, passwd, cgwlog)) == NULL )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }

    

    printf("Creating blob table ...\n");

    CGStmt *pStmt;
    pStmt = cego_prepare("create table blobtab ( a blob );");
    printf("Execute stmt ...\n");
    if ( cego_execute(cgdb, pStmt, 0) != 0)
    {
	printf("Error : %s\n", cgerrmsg); 
	exit(1);
    }
    cego_free_stmt(pStmt);
    
    // create blob ( putblob )
    
    CGBlob b;
    int blobSize = 100;
    b.buf = malloc(blobSize);
    int i;
    for ( i = 0 ; i < blobSize ; i++ )
	b.buf[i]='X';
    
    b.len = blobSize;
    b.fileId = 0;
    b.pageId = 0;
       
    cego_putblob (cgdb, &b);
    printf("Created blob with ref : [%d,%d]\n", b.fileId, b.pageId); 

    // insert into blobtab

    pStmt = cego_prepare("insert into blobtab values ( ? );");

    CGVal v1;
    v1.type = CG_BLOB;
    v1.len = 2 * sizeof(int);
    v1.val = malloc ( 2 * sizeof(int));
    
    memcpy ( v1.val, &b.fileId, sizeof(int));
    memcpy ( (int*)((long)v1.val + sizeof(int)), &b.pageId, sizeof(int));
    
    printf("Bind stmt ...\n");
    cego_bind_in(pStmt, &v1, 1);

    printf("Execute stmt ...\n");
    if ( cego_execute(cgdb, pStmt, 0) != 0)
    {
	printf("Error : %s\n", cgerrmsg); 
    }
    printf("Prepared Stmt ok\n");

    // blob retrievel
    // cego_disconnect(cgdb);
    // return;

    // select from blobtab
    
    printf("Creating fetch handle ...\n");
    CGFetch* cgfetch = cego_allocate_fetch();

    printf("Creating fetch handle ...\n");
    if ( cego_query(cgdb, "select a from blobtab;", cgfetch) != 0 )
    {
	printf("Error : %s\n", cgerrmsg);
	exit(1);
    }
    
    printf("NumCol=%d\n", cego_num_col(cgfetch));
    
    CGVal cgval[1];
    
    int fileId;
    int pageId;

    int colnum;
    while ( ( colnum = cego_fetch (cgfetch, cgval, 1)) > 0 )
    {
	int i=0;
	while ( i < colnum )
	{
	    if ( cgval[i].type == CG_BLOB )
	    {
		
		memcpy ( &fileId, (int*)cgval[i].val, sizeof (int));
		memcpy ( &pageId, (int*)( (long)cgval[i].val + sizeof(int)), sizeof (int));
		
		printf("FileId = %d", fileId);
		printf("PageId = %d", pageId);

	    }
	    i++;
	}
	printf("\n");
    }

    printf("Fetch ok\n");
    // cego_free_fetch(cgfetch);    

    printf("Retrieving blob  : [%d,%d]\n", fileId, pageId); 
    
    CGBlob b2;
    b2.len = 0;
    b2.buf = 0;
    
    b2.fileId = fileId;
    b2.pageId = pageId;
       
    cego_getblob (cgdb, &b2);

    printf("Retrieved blob of size : %d ... %s\n", b2.len, b2.buf); 
    

    pStmt = cego_prepare("drop table blobtab;");
    printf("Execute stmt ...\n");
    if ( cego_execute(cgdb, pStmt, 0) != 0)
    {
	printf("Error : %s\n", cgerrmsg); 
	exit(1);
    }
    cego_free_stmt(pStmt);
   
    cego_disconnect(cgdb);
}
    
