[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gambas-devel
Subject:    [Gambas-devel] Gambas & ODBC
From:       Andrea Bortolan <andrea_bortolan () yahoo ! it>
Date:       2005-01-26 15:04:39
Message-ID: 20050126150439.49847.qmail () web25204 ! mail ! ukl ! yahoo ! com
[Download RAW message or body]

Hi all,
you can find the new version of the ODBC module in the
attached files.
Please remember that its still in pre-alpha stage...
You can test it using the Database example,all the
buttons (Delete table, Create table and Fill table
buttons) will perform the correct action .
I tested it connected to a MySQL and an iSeries-DB2,
the example create the tables, delete the tables and
fill the table correctly.

Have a nice day, Andrea


		
___________________________________ 
Nuovo Yahoo! Messenger: E' molto più divertente: Audibles, Avatar, Webcam, Giochi, \
Rubrica… Scaricalo ora!  http://it.messenger.yahoo.it


["main.c" (text/x-c)]

/***************************************************************************

  main.c

  ODBC (unixODBC) driver
  (c) 2004-2005 Andrea Bortolan
  (c) 2000-2003 Beno� Minisini <gambas@users.sourceforge.net>

  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 1, 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; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

***************************************************************************/





#define __MAIN_C

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <math.h>

#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>

#include "main.h"


GB_INTERFACE GB;
DB_INTERFACE DB;


static char _buffer[32];
static DB_DRIVER _driver;





typedef
	struct {
	SQLHENV  V_OD_Env; 
	SQLHDBC  V_OD_hdbc; 
	}
ODBC_CONN;




typedef 
	struct {
	SQLCHAR fieldname[32];
	int fieldid;
	SQLSMALLINT type;
	SQLINTEGER outlen;
	SQLCHAR *fieldata;
	struct ODBC_FIELDS *next; 
	//struct ODBC_FIELDS *prev;
	}
ODBC_FIELDS;

typedef 
	struct {
	SQLHSTMT V_OD_hstmt;
	ODBC_FIELDS *fields; 
	}
ODBC_RESULT;
		


typedef 
	struct {
	char *tablename;
	struct ODBC_TABLES *next; 
	}
ODBC_TABLES;






/* Internal function to convert a database type into a Gambas type */

static GB_TYPE conv_type(int type)
{
  //printf("conv_type");
  switch(type)
  {
    case SQL_BINARY:
      return GB_T_BOOLEAN;

    /*case INT8OID:*/
    case SQL_NUMERIC:
    case SQL_DECIMAL:
    case SQL_INTEGER:
    case SQL_SMALLINT:
      return GB_T_INTEGER;

    case SQL_FLOAT:
    case SQL_REAL:
    case SQL_DOUBLE:
      return GB_T_FLOAT;

    case SQL_DATETIME:
    case SQL_TYPE_DATE:
    case SQL_TYPE_TIME:
    case SQL_TYPE_TIMESTAMP:
      return GB_T_DATE;

    case SQL_CHAR:
    default:
      return GB_T_STRING;

  }
}


/* Internal function to convert a database boolean value  */

static int conv_boolean(const char *data)
{
  return strcasecmp(data, "t") == 0 || strcasecmp(data, "'t'") == 0;
}

/* Internal function to convert a database value into a Gambas variant value */

static void conv_data(char *data, GB_VARIANT_VALUE *val, int type)
{
  GB_VALUE conv;
  GB_DATE_SERIAL date;
  double sec;
  long len;
  int bc;
//printf("conv_data");
  switch (type)
  {
/*    case BOOLOID:

      val->_boolean.type = GB_T_BOOLEAN;
      val->_boolean.value = conv_boolean(data);
      break;
*/
    /*case INT8OID:*/
    
    case SQL_BINARY:
    
    val->_boolean.type = GB_T_BOOLEAN;
    val->_boolean.value = atoi(data) != 0;
      break;
    
    case SQL_NUMERIC:
    case SQL_DECIMAL:
    case SQL_INTEGER:
    case SQL_SMALLINT:
    
      GB.NumberFromString(GB_NB_READ_INTEGER, data, strlen(data), &conv);

      val->_integer.type = GB_T_INTEGER;
      val->_integer.value = ((GB_INTEGER *)&conv)->value;

      break;

    case SQL_FLOAT:
    case SQL_REAL:
    case SQL_DOUBLE:

      GB.NumberFromString(GB_NB_READ_FLOAT, data, strlen(data), &conv);

      val->_float.type = GB_T_FLOAT;
      val->_float.value = ((GB_FLOAT *)&conv)->value;

      break;

      
    case SQL_TYPE_DATE:
    case SQL_TYPE_TIME:
    case SQL_TYPE_TIMESTAMP:
    //case FIELD_TYPE_TIMESTAMP:

      memset(&date, 0, sizeof(date));

      switch(type)
      {
        case SQL_TYPE_DATE:

          sscanf(data, "%4hu-%2hu-%2hu", &date.year, &date.month, &date.day);
	  
          break;

        case SQL_TYPE_TIME:
	 
          sscanf(data, "%4hu:%2hu:%lf", &date.hour, &date.min, &sec);
          date.sec = (short)sec;
          date.msec = (short)(sec * 1000 + 0.5);
          break;

     /*   case FIELD_TYPE_DATETIME:

          sscanf(data, "%4hu-%2hu-%2hu %2hu:%2hu:%lf", &date.year, &date.month, \
&date.day, &date.hour, &date.min, &sec);  date.sec = (short)sec;
          date.msec = (short)(sec * 1000 + 0.5);
          break;
*/
        case SQL_TYPE_TIMESTAMP:
	 len = strlen(data);
      if (len > 3 && strcmp(&data[len - 2], "BC") == 0)
        bc != 0;
      else
        bc = 0;
	
          sscanf(data, "%4hu-%2hu-%2hu %2hu:%2hu:%lf", &date.year, &date.month, \
&date.day, &date.hour, &date.min, &sec);  date.sec = (short)sec;
          date.msec = (short)(sec * 1000 + 0.5);
          break;
	  
	  if (bc)
        date.year = (-date.year);

      GB.MakeDate(&date, (GB_DATE *)&conv);

      val->_date.type = GB_T_DATE;
      val->_date.date = ((GB_DATE *)&conv)->value.date;
      val->_date.time = ((GB_DATE *)&conv)->value.time;
      break;
      }      
      
      
      
      
      
      

    case SQL_CHAR:
    default:

      //val->_string.type = GB_T_STRING;
      //GB.NewString(&val->_string.value, data, 0);
      val->_string.type = GB_T_CSTRING;
      val->_string.value = data;

      break;
  }

}


/* Internal function to substitute the table name into a query */

static char *query_param[3];

static void query_get_param(int index, char **str, long *len)
{
  if (index > 3)
    return;

  index--;
  *str = query_param[index];
  *len = strlen(*str);
}



/*****************************************************************************

  get_quote()

  Returns the character used for quoting object names.

*****************************************************************************/

static char *get_quote(void)
{
  return QUOTE_STRING;
}

/*****************************************************************************

  open_database()

  Connect to a database.

  <desc> points at a structure describing each connection parameter.

  This function must return a database handle, or NULL if the connection
  has failed.

  The name of the database can be NULL, meaning a default database.

*****************************************************************************/

/* Internal function to allocate the ODBC handle */
static ODBC_CONN *SQL_Handle(void)
{
  return (malloc (sizeof(ODBC_CONN)));
  
}

void SQL_Handle_free(ODBC_CONN *ptr)
{
 if (ptr!=NULL) free(ptr);
  
}


static DB_DATABASE open_database(DB_DESC *desc, char **charset)
{

long V_OD_erg; 
ODBC_CONN *odbc;
	


	/* Allocate the ODBC handle */
	odbc=SQL_Handle();
	odbc->V_OD_hdbc=NULL;
	/* Allocate the Environment handle */
	V_OD_erg=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&odbc->V_OD_Env);
	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
	{
		free (odbc);
		GB.Error ("ODBC ERROR");
		printf("ODBC - Unable to allocate the Environment Handle\n");
		return NULL;
	}

	/* Set the Envoronment attributes */
	V_OD_erg=SQLSetEnvAttr(odbc->V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, \
0);

	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
	{
		SQLFreeHandle(SQL_HANDLE_ENV, odbc->V_OD_Env);
		free(odbc);
		GB.Error ("ODBC ERROR");
		printf("ODBC - Unable to set the Environment attributes\n");
		return NULL;
	}
	
        /* Allocate the Database Connection handle */
	V_OD_erg = SQLAllocHandle(SQL_HANDLE_DBC, odbc->V_OD_Env, &odbc->V_OD_hdbc); 
	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
	{
		SQLFreeHandle(SQL_HANDLE_ENV, odbc->V_OD_Env);
		free(odbc);
		GB.Error ("ODBC ERROR");
		printf("ODBC - Unable to allocate the ODBC handler\n");
		return NULL;
	
	}
	
	/* Connect to Database (Data Source Name) */
	V_OD_erg = SQLConnect(odbc->V_OD_hdbc, (SQLCHAR*) desc->host, \
SQL_NTS,desc->user,SQL_NTS, desc->password, SQL_NTS);  if ((V_OD_erg != SQL_SUCCESS) \
&& (V_OD_erg != SQL_SUCCESS_WITH_INFO))  {
		SQLFreeHandle(SQL_HANDLE_DBC, odbc->V_OD_hdbc);
		SQLFreeHandle(SQL_HANDLE_ENV, odbc->V_OD_Env);
		free(odbc);
		GB.Error ("ODBC ERROR Unable to connect to DSN");
		printf("ODBC - Unable to connect to DSN\n");
		return NULL;
		
	}
	V_OD_erg=SQLSetConnectAttr(odbc->V_OD_hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON, 0);

desc->version=(char) "odbc";
return (DB_DATABASE) odbc;

}

/*****************************************************************************

  close_database()

  Terminates the database connection.

  <handle> contains the database handle.

*****************************************************************************/

static void close_database(DB_DATABASE handle)
{
    //SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);
    ODBC_CONN *conn = (ODBC_CONN *) handle;
    SQLDisconnect(conn);
    SQLFreeHandle(SQL_HANDLE_DBC,conn->V_OD_hdbc);
    SQLFreeHandle(SQL_HANDLE_ENV, conn->V_OD_Env);
    if (conn !=NULL )SQL_Handle_free (conn);
    
}


/*****************************************************************************

  format_value()

  This function transforms a gambas value into a string value that can
  be inserted into a SQL query.

  <arg> points to the value.
  <add> is a callback called to insert the string into the query.

  This function must return TRUE if it translates the value, and FALSE if
  it does not.

  If the value is not translated, then a default translation is used.

*****************************************************************************/

static int format_value(GB_VALUE *arg, DB_FORMAT_CALLBACK add)
{
 
   char *s;
  int l;
  int i;
  GB_DATE_SERIAL *date;

  switch (arg->type)
  {
    case GB_T_BOOLEAN:
/*Note this is likely to go to a tinyint  */

      if (VALUE((GB_BOOLEAN *)arg))
         add("'1'", 3);
      else
        add("'0'", 3);
      return TRUE;

    case GB_T_STRING:
    case GB_T_CSTRING:
      
      s = VALUE((GB_STRING *)arg).addr + VALUE((GB_STRING *)arg).start;
      l = VALUE((GB_STRING *)arg).len;

      if (arg->type == GB_T_STRING)
         add("'", 1);

      for (i = 0; i < l; i++, s++)
      {
        add(s, 1);
        if (*s == '\'' || *s == '\\')
          add(s, 1);
      }
  
      if (arg->type == GB_T_STRING)
         add("'", 1);

      return TRUE;

    case GB_T_DATE:

      date = GB.SplitDate((GB_DATE *)arg);

      l = sprintf(_buffer, "'%04d-%02d-%02d-%02d.%02d.%02d.",
          date->year, date->month, date->day,
          date->hour, date->min, date->sec);

          add(_buffer, l);

          if (date->msec)
          {
            l = sprintf(_buffer, ".%03d", date->msec);
            add(_buffer, l);
          }

          add("'", 1);

          return TRUE;

    default:
      return FALSE;
  }
}


 ODBC_RESULT *SQL_Result(void)
{
 return (malloc (sizeof(ODBC_RESULT)));
}

static void SQL_Result_Free(ODBC_RESULT *ptr)
{
if (ptr!=NULL) free (ptr);
 return ;
}
/* Internal function to implement the query execution */

 int do_query(ODBC_CONN *handle, const char *error, ODBC_RESULT **res, const char \
*query, int nsubst, ...) {


long V_OD_erg; 
ODBC_RESULT *odbcres;
int memory=0;


        /* Allocate the spase for the result structure */
	if (res != NULL){
	odbcres=SQL_Result();
	
	*res = odbcres;
	
        }
	/* Allocate the Statement handle */
	
	// Questa modifica causa il segfault !!!!! togliere l'if e mantenere SQLALLOCHNDLEr
	//if (res ==NULL){
		//printf(" res è null  alloco l'odbcres\n");
	 	//if (res ==NULL) odbcres=SQL_Result();
	 	
	 	if(odbcres->V_OD_hstmt != NULL)
		{
		
		 	V_OD_erg=SQLAllocHandle(SQL_HANDLE_STMT, handle->V_OD_hdbc, \
&odbcres->V_OD_hstmt);  
		}else
		{
			memory=1;
			odbcres=SQL_Result();
		 	V_OD_erg=SQLAllocHandle(SQL_HANDLE_STMT, handle->V_OD_hdbc, \
&odbcres->V_OD_hstmt);  }
		 
		 
	
		if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
    		{
			//if (res == NULL) SQL_Result_Free(odbcres);
			GB.Error("ODBC Error executing the SQL statement");
			printf("ODBC - Error Executing the SQL statement %s, \
l'errore%u\n",query,V_OD_erg);  return V_OD_erg ;
		}
	
        //}
	/* Set the Statement's attributes */
	V_OD_erg=SQLSetStmtAttr( \
odbcres->V_OD_hstmt,SQL_ATTR_CURSOR_SCROLLABLE,(SQLPOINTER)SQL_SCROLLABLE, 0 );  
	
        /* Execute the query */
	
	V_OD_erg=SQLExecDirect(odbcres->V_OD_hstmt , (char *)query , SQL_NTS);
	
	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
    	{
		GB.Error("ODBC Error executing the statement.");
		//if (res == NULL) SQL_Result_Free(odbcres);
		printf("ODBC - Error Executing the statement. %s\n",query);
		
		return V_OD_erg ;
    	}
        
	if (memory == 1) SQL_Result_Free(odbcres);
	
	

return V_OD_erg;

}



/*****************************************************************************

  exec_query()

  Send a query to the server and gets the result.

  <handle> is the database handle, as returned by open_database()
  <query> is the query string.
  <result> will receive the result handle of the query.
  <err> is an error message used when the query failed.

  <result> can be NULL, when we don't care getting the result.

*****************************************************************************/


static int exec_query(DB_DATABASE handle, char *query, DB_RESULT *result, char *err)
{
//printf ("la query da eseguire %s\n",query);
  return do_query((ODBC_CONN *)handle, err, (ODBC_RESULT **)result, query, 0);
}






/*****************************************************************************

  query_init()

  Initialize an info structure from a query result.

  <result> is the handle of the query result.
  <info> points to the info structure.
  <count> will receive the number of records returned by the query.

  This function must initialize the info->nfield field with the number of
  field in the query result.

*****************************************************************************/

static void query_init(DB_RESULT result, DB_INFO *info, int *count)
{

long V_OD_erg; 
ODBC_RESULT *res = (ODBC_RESULT *) result;
SQLINTEGER   V_OD_rowanz;
SQLSMALLINT  V_OD_colanz;


V_OD_erg=SQLNumResultCols(res->V_OD_hstmt,&V_OD_colanz);
    if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
    {
    	printf("ODBC - Error getting the number of coloumns\n");
	return ;
    }
    
V_OD_erg=SQLRowCount(res->V_OD_hstmt,&V_OD_rowanz);
    if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
    {
	printf("ODBC - Error getting the number of rows\n");
      	return ;
    }

  
  *count=V_OD_rowanz;
  info->nfield = V_OD_colanz;
 
  query_make_result(res);
  
}


/*****************************************************************************

  query_release()

  Free the info structure filled by query_init() and the result handle.

  <result> is the handle of the query result.
  <info> points to the info structure.

*****************************************************************************/

static void query_release(DB_RESULT result, DB_INFO *info)
{
  ODBC_RESULT *res = (ODBC_RESULT *) result;
  if (res!=NULL)query_free_result(res);
  SQLFreeHandle(SQL_HANDLE_STMT,res->V_OD_hstmt);
  
  //free(res); 
}


/* Internal function - free the result structure create to allocate the result row */
static void query_free_result (ODBC_RESULT *result)
{
    
    SQLSMALLINT      V_OD_colanz;
    ODBC_FIELDS *current;
    int i,nresultcols;
    
    
    SQLNumResultCols(result->V_OD_hstmt,&V_OD_colanz);
    
    nresultcols=V_OD_colanz;
    
	for (i = nresultcols; i >= 0; i--) {
        
		current=result->fields;
		int x;
		for (x=i; x > 0 ; x--) {
		
			current = current->next;
				
		}
		
		if (current != NULL) {
		        free(current->fieldata);
			free (current);
		
		}
		
	}
  
}



/* Internal function - create the space for the result and bind the column to each \
field-space allocated */ static void query_make_result( ODBC_RESULT *result)
{

    SQLCHAR         colname[32];
    SQLSMALLINT     colnamelen;
    SQLUINTEGER     precision;
    SQLSMALLINT     scale;
    SQLINTEGER      i;
    SQLINTEGER      displaysize;
    SQLSMALLINT      V_OD_colanz;
    ODBC_FIELDS *field,*current;
    SQLINTEGER collen;
    int nresultcols;
    
    
    SQLNumResultCols(result->V_OD_hstmt,&V_OD_colanz);
    
    nresultcols=V_OD_colanz;
    result->fields=NULL;
        
    
    
    for (i = 0; i < nresultcols; i++) 
    {    
        field = malloc(sizeof(ODBC_FIELDS));
        
        if (result->fields == NULL) {
	
		result->fields = field;
	} 
	else {
	
		current->next = (ODBC_FIELDS *)field;
	}
        
	current = field;
    
        SQLDescribeCol(result->V_OD_hstmt, i + 1, current->fieldname, \
                sizeof(current->fieldname),&colnamelen, &current->type, &precision, \
                &scale, NULL);
        collen = precision; /* Note, assignment of unsigned int to signed */
 	
        /* Get display length for column */
        SQLColAttribute(result->V_OD_hstmt, i + 1, SQL_COLUMN_DISPLAY_SIZE, NULL, 0, \
NULL, &displaysize);  
	/*
         * Set column length to max of display length, and column name
         * length. Plus one byte for null terminator
         */
	 
	 if (displaysize >= strlen((char*) colname))
	 {
	 	collen=displaysize+1;
	 } 
	 else
	 {
        	collen = strlen((char *) colname) + 1;
  	 }	
 
        /* Allocate memory to bind column                             */
        
		
	current->fieldata=(SQLCHAR *) malloc(collen);
	        
	current->next=NULL;
        
	/* Bind columns to program vars, converting all types to CHAR */
         SQLBindCol(result->V_OD_hstmt, i + 1, SQL_C_CHAR, current->fieldata, collen, \
&current->outlen);  
    }
 

}



/*****************************************************************************

  query_fill()

  Fill a result buffer with the value of each field of a record.

  <result> is the handle of the result.
  <pos> is the index of the record in the result.
  <buffer> points to an array having one element for each field in the
  result.

  This function must use GB.StoreVariant() to store the value in the
  buffer.

*****************************************************************************/


static void query_fill(DB_RESULT result, int pos, GB_VARIANT_VALUE *buffer, int next)
{
    ODBC_RESULT *res = (ODBC_RESULT *) result;
    GB_VARIANT      value;
    SQLRETURN       rc;
    SQLINTEGER      i;
    SQLSMALLINT     V_OD_colanz;
    ODBC_FIELDS     *current;
    int             nresultcols;
    
        
	SQLNumResultCols(res->V_OD_hstmt,&V_OD_colanz);
   
        nresultcols=V_OD_colanz;

	
	if (!next){
		rc = SQLFetchScroll( res->V_OD_hstmt, SQL_FETCH_ABSOLUTE, pos+1 );
	}
	else {
		//rc=SQLFetch(hstmt);
		rc = SQLFetchScroll( res->V_OD_hstmt, SQL_FETCH_ABSOLUTE, pos+1 );
		
	
	}
	
	
	
	if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO)) \
GB.Error("ODBC_END_OF_DATA");  current=res->fields;
	
	if (rc  != SQL_NO_DATA_FOUND) {
		//errmsg[0] = '\0';
		
        	for (i = 0; i < nresultcols; i++) {
		
			value.type = GB_T_VARIANT;
        		value.value._object.type = GB_T_NULL;

        		
        		if (current){
				
				//printf("chiede la conversione del dato del campo %i che contiene %s \
\n",i,current->fieldata);  conv_data(current->fieldata, &value.value, current->type);
        		}
			
        		GB.StoreVariant(&value, &buffer[i]);
			
			current=current->next;
	
        	} /* for all columns in this row  */
 
        	
    
    	} /* while rows to fetch */
 	
}


/*****************************************************************************

  field_name()

  Return the name of a field in a result from its index.

  <result> is the result handle.
  <field> is the field index.

*****************************************************************************/



static char *field_name(DB_RESULT result, int field)
{

    SQLCHAR         colname[32];
    SQLSMALLINT     coltype;
    SQLSMALLINT     colnamelen;
    SQLUINTEGER     precision;
    SQLSMALLINT     scale;
    char            *colnamer ;
    ODBC_RESULT *res = (ODBC_RESULT *) result;	 
        
  	SQLDescribeCol(res->V_OD_hstmt, field + 1, colname, sizeof(colname),&colnamelen, \
&coltype, &precision, &scale, NULL);  colnamer = malloc(sizeof  (char) * \
strlen(colname)+1);  strcpy(colnamer,colname);
  	//printf("Field name : %s, colonna : %d\n",colnamer,field);
  	return colnamer; 
}


/*****************************************************************************

  field_index()

  Return the index of a field in a result from its name.

  <result> is the result handle.
  <name> is the field name.
  <handle> is needed by this driver to enable table.field syntax

*****************************************************************************/

static int field_index(DB_RESULT result, char *name, DB_DATABASE handle, long \
version) { 
    SQLCHAR         colname[32];
    SQLSMALLINT     coltype;
    SQLSMALLINT     colnamelen;
    SQLUINTEGER     precision;
    SQLSMALLINT     scale;
    SQLSMALLINT     V_OD_colanz;
    int             field;
    ODBC_RESULT *res = (ODBC_RESULT *) result;
    
 SQLNumResultCols(res->V_OD_hstmt,&V_OD_colanz);
  //printf("filed_index %s\n",name);
  
  for (field = 0; field < V_OD_colanz; field++) {
  	SQLDescribeCol(res->V_OD_hstmt, field + 1, colname, sizeof(colname),&colnamelen, \
&coltype, &precision, &scale, NULL);  //	printf("Field index  -- nome richiesto : %s, \
nome colonna : %s, id : %u\n",name,colname,field);  
	if  (strcmp(name,colname)==0){
  		return (int) (field);
  	}
	
  }

  return (0);
}


/*****************************************************************************

  field_type()

  Return the Gambas type of a field in a result from its index.

  <result> is the result handle.
  <field> is the field index.

*****************************************************************************/

static GB_TYPE field_type(DB_RESULT result, int field)
{

    SQLCHAR         colname[32];
    SQLSMALLINT     coltype;
    SQLSMALLINT     colnamelen;
    SQLUINTEGER     precision;
    SQLSMALLINT     scale;
    ODBC_RESULT *res = (ODBC_RESULT *) result;
  
     SQLDescribeCol(res->V_OD_hstmt, field + 1, colname, sizeof(colname),&colnamelen, \
&coltype, &precision, &scale, NULL);

  
     return conv_type(coltype); 
}


/*****************************************************************************

  field_length()

  Return the length of a field in a result from its index.

  <result> is the result handle.
  <field> is the field index.

*****************************************************************************/

static int field_length(DB_RESULT result, int field)
{
    SQLCHAR         colname[32];
    SQLSMALLINT     coltype;
    SQLSMALLINT     colnamelen;
    SQLUINTEGER     precision;
    SQLSMALLINT     scale;
    ODBC_RESULT *res = (ODBC_RESULT *) result;
  
  SQLDescribeCol(res->V_OD_hstmt, field + 1, colname, sizeof(colname),&colnamelen, \
&coltype, &precision, &scale, NULL);  return colnamelen;

}


/*****************************************************************************

  begin_transaction()

  Begin a transaction.

  <handle> is the database handle.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int begin_transaction(DB_DATABASE handle)
{
//printf("Begin transaction \n");
  //ODBC_CONN *conn = (ODBC_CONN *) handle;
  //return (do_query(conn,"Unable to begin transaction: &1",NULL,"BEGIN",0));
}


/*****************************************************************************

  commi_transaction()

  Commit a transaction.

  <handle> is the database handle.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int commit_transaction(DB_DATABASE handle)
{
  ODBC_CONN *conn = (ODBC_CONN *) handle;
  ODBC_RESULT *res;
  int exit;
  
  exit= (do_query(conn,"Unable to commit transaction: &1",&res,"COMMIT",0));
  if (res !=NULL){ 
  	free(res);
  }
  return (exit);
}


/*****************************************************************************

  rollback_transaction()

  Rolllback a transaction.

  <handle> is the database handle.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int rollback_transaction(DB_DATABASE handle)
{
  ODBC_CONN *conn = (ODBC_CONN *) handle;
  ODBC_RESULT *res;
  int exit;
  exit=(do_query(conn,"Unable to rollback transaction: &1",&res,"ROLLBACK",0));
  if(res!=NULL) free(res);
  return(exit);

}


/*****************************************************************************

  table_init()

  Initialize an info structure from table fields.

  <handle> is the database handle.
  <table> is the table name.
  <info> points at the info structure.

  This function must initialize the following info fields:
   - info->nfield must contain the number of fields in the table.
   - info->fields is a char*[] pointing at the name of each field.
   - info->types is a GB_TYPE[] giving the gambas type of each field.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int table_init(DB_DATABASE db, char *table, DB_INFO *info)
{


    SQLCHAR         colname[32];
    SQLSMALLINT     coltype;
    //SQLSMALLINT     colltype[200];
    SQLSMALLINT     colnamelen;
    //SQLSMALLINT     nullable;
    //SQLINTEGER      collen[200];
    SQLUINTEGER     precision;
    SQLSMALLINT     scale;
    SQLHSTMT hstmt = db ;
    int i, n;
    SQLSMALLINT     V_OD_colanz,V_OD_erg;
    DB_FIELD *f;
    SQLCHAR         query[101]= "SELECT * FROM ";
    ODBC_CONN *conn = (ODBC_CONN *) db;
    ODBC_RESULT *odbcres;

  /* Nom de la table */
  
  strcpy (&query[14],table);
  GB.NewString(&info->table, table, 0);
  
  
  //ODBC_CONN *conn = (ODBC_CONN *) handle;
  
  //strcpy (&query[15],table);
  
  odbcres=SQL_Result();
  V_OD_erg=SQLAllocHandle(SQL_HANDLE_STMT, conn->V_OD_hdbc, &odbcres->V_OD_hstmt);
  
  V_OD_erg=SQLExecDirect(odbcres->V_OD_hstmt , (char *)query , SQL_NTS);
  
  //do_query(conn,"Cannot Initialize an info structure:&1",&odbcres,query,0);
  //return  do_query(conn,"Cannot delete table:&1",NULL,"COMMIT",0);
  if (SQLNumResultCols(odbcres->V_OD_hstmt,&V_OD_colanz)!= SQL_SUCCESS)
  {
  
  GB.Error("Error getting info from table");
  }

  
  
  n= info->nfield = V_OD_colanz; //= n = mysql_num_fields(res);

  if (n == 0)
    return 1;

  GB.Alloc((void **)&info->field, sizeof(DB_FIELD) * n);

  i = 0;

  while (SQLDescribeCol(odbcres->V_OD_hstmt, i + 1, colname, \
sizeof(colname),&colnamelen, &coltype, &precision, &scale, NULL)==SQL_SUCCESS)  {
  
    f = &info->field[i];
    GB.NewString(&f->name, colname, 0);
    f->type = conv_type(coltype);
    f->length = 0;
    if (f->type == GB_T_STRING)
      f->length = precision;
    i++;
  
  }
if (odbcres != NULL){SQL_Result_Free (odbcres);}
  //mysql_free_result(res);

  return 0;
  
}




/*****************************************************************************

  table_index()

  Initialize an info structure from table primary index.

  <handle> is the database handle.
  <table> is the table name.
  <info> points at the info structure.

  This function must initialize the following info fields:
   - info->nindex must contain the number of fields in the primary index.
   - info->index is a int[] giving the index of each index field in
     info->fields.

  This function must be called after table_init().

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int table_index(DB_DATABASE db, char *table, DB_INFO *info)
{
//  printf("qui14\n"); 
}


/*****************************************************************************

  table_release()

  Free the info structure filled by table_init() and/or table_index()

  <handle> is the database handle.
  <info> points at the info structure.

*****************************************************************************/

static void table_release(DB_DATABASE db, DB_INFO *info)
{
  /* All is done outside the driver */
}


/*****************************************************************************

  table_exist()

  Returns if a table exists

  <handle> is the database handle.
  <table> is the table name.

  This function returns TRUE if the table exists, and FALSE if not.

*****************************************************************************/

static int table_exist(DB_DATABASE handle, char *table)
{
  
  
        SQLHSTMT        hstmt;
	SQLRETURN	V_OD_erg,nReturn    = -1;
	SQLCHAR         szTableName[101]    = "";
	SQLCHAR         szTableType[101]    = "";
	SQLCHAR         szTableRemarks[301] = "";
	SQLLEN	    	nIndicatorName;
	SQLLEN		nIndicatorType;
	SQLLEN		nIndicatorRemarks;
	int 		compare=-1;
        ODBC_CONN *han = (ODBC_CONN *) handle;
	
	V_OD_erg=SQLAllocHandle(SQL_HANDLE_STMT, han->V_OD_hdbc, &hstmt);
	
	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
    	{
    		return V_OD_erg ;
	}
	
	

	// EXECUTE OUR SQL/CALL
	if ( SQL_SUCCESS != (nReturn=SQLTables( hstmt, 0, 0, 0, 0, 0, 0, 0, 0 )) )
	{
		
		return;
	}

	SQLBindCol( hstmt, SQLTables_TABLE_NAME, SQL_C_CHAR, szTableName, \
                sizeof(szTableName), &nIndicatorName );
        SQLBindCol( hstmt, SQLTables_TABLE_TYPE, SQL_C_CHAR, szTableType, \
                sizeof(szTableType), &nIndicatorType );
        SQLBindCol( hstmt, SQLTables_REMARKS, SQL_C_CHAR, szTableRemarks, \
sizeof(szTableRemarks), &nIndicatorRemarks );  // GET RESULTS
	nReturn = SQLFetch( hstmt );
	while ( (nReturn == SQL_SUCCESS || nReturn == SQL_SUCCESS_WITH_INFO) && compare != \
0)  {
		
	//printf("le tabelle in comparazione %s : %s\n",szTableName,table);	
        compare=strncmp(szTableName,table,sizeof(table));
        szTableName[0]      = '\0';
        szTableType[0]      = '\0';
        szTableRemarks[0]   = '\0';
	nReturn = SQLFetch( hstmt );
	}

	// FREE STATEMENT
	nReturn = SQLFreeHandle( hstmt, SQL_DROP );
	
	if (compare==0 ) return TRUE;
	 else return FALSE;
		
}



/*****************************************************************************

  table_list()

  Returns an array containing the name of each table in the database

  <handle> is the database handle.
  <tables> points to a variable that will receive the char* array.

  This function returns the number of tables, or -1 if the command has
  failed.

  Be careful: <tables> can be NULL, so that just the count is returned.

*****************************************************************************/

static long table_list(DB_DATABASE handle, char ***tables, long version)
{
 

        ODBC_TABLES     tablelist,*curtable;
	SQLHSTMT        hstmt;
	SQLRETURN	V_OD_erg,nReturn    = -1;
	SQLCHAR         szTableName[101]    = "";
	SQLCHAR         szTableType[101]    = "";
	SQLCHAR         szTableRemarks[301] = "";
	SQLLEN		nIndicatorName;
	SQLLEN		nIndicatorType;
	SQLLEN		nIndicatorRemarks;
        int 		tablenum=0;
	int 		i;
	ODBC_CONN *han = (ODBC_CONN *) handle;
	
	V_OD_erg=SQLAllocHandle(SQL_HANDLE_STMT, han->V_OD_hdbc, &hstmt);
	
	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
    	{
    		return V_OD_erg ;
	}
	
	curtable=&tablelist;
        
	// EXECUTE OUR SQL/CALL
	if ( SQL_SUCCESS != (nReturn=SQLTables( hstmt, 0, 0, 0, 0, 0, 0, 0, 0 )) )
	{
		
		return;
	}

	SQLBindCol( hstmt, SQLTables_TABLE_NAME, SQL_C_CHAR, szTableName, \
                sizeof(szTableName), &nIndicatorName );
        SQLBindCol( hstmt, SQLTables_TABLE_TYPE, SQL_C_CHAR, szTableType, \
                sizeof(szTableType), &nIndicatorType );
        SQLBindCol( hstmt, SQLTables_REMARKS, SQL_C_CHAR, szTableRemarks, \
sizeof(szTableRemarks), &nIndicatorRemarks );  // GET RESULTS
	nReturn = SQLFetch( hstmt );
	
	if (nReturn != SQL_SUCCESS && nReturn != SQL_SUCCESS_WITH_INFO) {
	 
		SQLFreeHandle( hstmt, SQL_DROP );
		return (-1);
	 
	}
	 
	 
	while ( nReturn == SQL_SUCCESS || nReturn == SQL_SUCCESS_WITH_INFO )
	{	
	
  		
		tablenum=tablenum+1;					
        	curtable->tablename=malloc(sizeof(szTableName));
		curtable->next=malloc(sizeof(ODBC_TABLES));
		strncpy(curtable->tablename,szTableName,sizeof(szTableName));
		curtable=curtable->next;
        	szTableName[0]      = '\0';
        	szTableType[0]      = '\0';
        	szTableRemarks[0]   = '\0';
		nReturn = SQLFetch( hstmt );
	}

	// FREE STATEMENT
	nReturn = SQLFreeHandle( hstmt, SQL_DROP );
	
	GB.NewArray(tables, sizeof(char *), tablenum);
	

	
	curtable=&tablelist ;
	for (i=0 ; i<tablenum;i++){
	
	//printf("nome : \t%s,\t indirizzo\t %p\t name \
%p\n",curtable->tablename,curtable,curtable->tablename);  GB.NewString(&(*tables)[i], \
curtable->tablename, 0);  free (curtable->tablename);
	curtable=curtable->next;
	
	}
	
	curtable=&tablelist ;
	int g;
	for (i=tablenum; i>0; i--){
	 
	
		for (g=0 ; g < i;g++){
	
		curtable=curtable->next;
	
		}
		//printf("table \t;%p\tname %p\n",curtable,curtable->tablename);
		
		free (curtable);
		
		curtable=&tablelist;
	
	}
	
 
return (tablenum);
}


/*****************************************************************************

  table_primary_key()

  Returns a string representing the primary key of a table.

  <handle> is the database handle.
  <table> is the table name.
  <key> points to a string that will receive the primary key.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int table_primary_key(DB_DATABASE handle, char *table, char ***primary)
{

	ODBC_TABLES     tablelist,*curtable;
	SQLHSTMT        hstmt;
	SQLRETURN	V_OD_erg,nReturn    = -1;
	SQLCHAR         szTableName[101]    = "";
	SQLCHAR         szKeyName[101]      ="";
	SQLCHAR         szTableType[101]    = "";
	SQLCHAR         szTableRemarks[301] = "";
	SQLCHAR		szColumnName[101]   = "";
	SQLCHAR         query[101]= "SELECT * FROM ";
	//QString         qsError;
	SQLLEN		nIndicatorName;
	SQLLEN		nIndicatorType;
	SQLLEN		nIndicatorRemarks;
	SQLSMALLINT              V_OD_colanz;
    	//classTable      *pTable = NULL;
        int tablenum=0;
	int i;
	ODBC_CONN *han = (ODBC_CONN *) handle;
	// CREATE A STATEMENT
	ODBC_RESULT res;
	//printf("Table List\n\n\n");
	//return 99;
	strcpy (&query[14],table);
	
	
	
	V_OD_erg=SQLAllocHandle(SQL_HANDLE_STMT, han->V_OD_hdbc, &hstmt);
	
	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
    	{
    		return V_OD_erg ;
	}

	if (do_query(han, "Unable to get primary key: &1", &res, query, 1, table))
    return TRUE;
	
	
	
if (!SQL_SUCCEEDED(nReturn=SQLPrimaryKeys( hstmt, 0, 0, 0, SQL_NTS, table, SQL_NTS ) \
) )  return  TRUE;

  // GET RESULTS
  
  
  
  SQLNumResultCols(hstmt,&V_OD_colanz);
  GB.NewArray(primary, sizeof(char *), V_OD_colanz);
  i=0;
  while (SQL_SUCCEEDED(SQLFetch( hstmt ) ) )
  {
    if (!SQL_SUCCEEDED(SQLGetData( hstmt, 4, SQL_C_CHAR, &szColumnName[0], \
sizeof(szColumnName), 0 ) ) )  strcpy( (char *)szColumnName, "Unknown" );

    if (!SQL_SUCCEEDED(SQLGetData( hstmt, 6, SQL_C_CHAR, &szKeyName[0], \
sizeof(szKeyName), 0 ) ) )  strcpy( (char *)szKeyName, "Unknown" );

    GB.NewString(&((*primary)[i]), szColumnName, 0);
    i++;
    //listColumns.append( pColumn = new classColumn( this, pColumn, pCanvas, hDbc, \
QString((char*)szColumnName).stripWhiteSpace(), "KEY", qsDesc ) );  }
SQLFreeHandle( hstmt, SQL_DROP );
//GB.NewArray(primary, sizeof(char *), PQntuples(res));

//  for (i = 0; i < PQntuples(res); i++)
//    GB.NewString(&((*primary)[i]), PQgetvalue(res, i, 0), 0);

//  PQclear(res);

  return FALSE;
 
}


/*****************************************************************************

  table_is_system()

  Returns if a table is a system table.

  <handle> is the database handle.
  <table> is the table name.

  This function returns TRUE if the table is a system table, and FALSE if
  not.

*****************************************************************************/

static int table_is_system(DB_DATABASE handle, char *table, long version)
{
  //printf("qui18\n"); 
}


/*****************************************************************************

  table_delete()

  Deletes a table.

  <handle> is the database handle.
  <table> is the table name.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int table_delete(DB_DATABASE handle, char *table)
{
  ODBC_CONN *conn = (ODBC_CONN *) handle;
  ODBC_RESULT *res;
  int exit;
  SQLCHAR         query[101]= "DROP TABLE ";
  strcpy (&query[11],table);
  exit = do_query(conn,"Cannot delete table:&1",&res,query,0);
  if (res!=NULL){ free (res);}
  if (exit==0){ 
  	exit= do_query(conn,"Cannot delete table:&1",&res,"COMMIT",0);
  }	
  if (res!=NULL){ free (res);}
  return (exit);
}


/*****************************************************************************

  table_create()

  Creates a table.

  <handle> is the database handle.
  <table> is the table name.
  <fields> points to a linked list of field descriptions.
  <key> is the primary key.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int table_create(DB_DATABASE handle, char *table, DB_FIELD *fields, char \
**primary, char *not_used) {

  //PGconn *conn = (PGconn *)handle;
  ODBC_CONN *conn = (ODBC_CONN *) handle;
  ODBC_RESULT *res;
  DB_FIELD *fp;
  int comma;
  char *type;
  int i,exit;

  DB.Query.Init();

  DB.Query.Add("CREATE TABLE ");
  DB.Query.Add(table);
  DB.Query.Add(" ( ");

  comma = FALSE;
  for (fp = fields; fp; fp = fp->next)
  {
    if (comma)
      DB.Query.Add(", ");
    else
      comma = TRUE;

    /*DB.Query.Add(QUOTE_STRING);*/
    DB.Query.Add(fp->name);
    /*DB.Query.Add(QUOTE_STRING);*/

    switch (fp->type)
    {
      case GB_T_BOOLEAN: type = "SMALLINT"; break;
      case GB_T_INTEGER: type = "INTEGER"; break;
      case GB_T_FLOAT: type = "FLOAT"; break;
      case GB_T_DATE: type = "TIMESTAMP"; break;
      case GB_T_STRING:

        if (fp->length <= 0)
          type = "TEXT";
        else
        {
          sprintf(_buffer, "VARCHAR(%ld)", fp->length);
          type = _buffer;
        }

        break;

      default: type = "TEXT"; break;
    }

    DB.Query.Add(" ");
    DB.Query.Add(type);

    if (fp->def.type != GB_T_NULL)
    {
      DB.Query.Add(" NOT NULL DEFAULT ");
      DB.FormatVariant(&_driver, &fp->def, DB.Query.AddLength);
    }
    else if (DB.StringArray.Find(primary, fp->name) >= 0)
    {
      DB.Query.Add(" NOT NULL ");
    }
  }

  if (primary)
  {
    DB.Query.Add(", PRIMARY KEY (");
  
    for (i = 0; i < GB.Count(primary); i++)
    {
      if (i > 0)
        DB.Query.Add(",");
  
      DB.Query.Add(primary[i]);
    }
    
    DB.Query.Add(")");
  }

  DB.Query.Add(" )");
  

  exit=do_query(conn, "Cannot create table: &1", &res, DB.Query.Get(), 0);
  if (res!=NULL){ free(res);}
  if(exit==0){ 
  	exit= do_query(conn,"Cannot create table:&1",&res,"COMMIT",0);
 }
 if (res!=NULL){ free(res);}
 return(exit);
//  GB.Error("Creazione Tabella");
}


/*****************************************************************************

  field_exist()

  Returns if a field exists in a given table

  <handle> is the database handle.
  <table> is the table name.
  <field> is the field name.

  This function returns TRUE if the field exists, and FALSE if not.

*****************************************************************************/

static int field_exist(DB_DATABASE handle, char *table, char *field)
{
  
// Da finire !!!!  
  


//static int field_index(ODBC_RESULT *result, char *name, DB_DATABASE handle, long \
version) //{ 
    
    SQLCHAR         colname[32];
    SQLSMALLINT     coltype;
    SQLSMALLINT     colnamelen;
    SQLUINTEGER     precision;
    SQLSMALLINT     scale;
    SQLSMALLINT              V_OD_colanz;
    int field;
    ODBC_TABLES     tablelist,*curtable;
    ODBC_RESULT     result;
    SQLHSTMT        hstmt;
    SQLRETURN		V_OD_erg,nReturn             = -1;
    SQLCHAR         szTableName[101]    = "";
    SQLCHAR         szTableType[101]    = "";
    SQLCHAR         szTableRemarks[301] = "";
	//QString         qsError;
    SQLLEN		    nIndicatorName;
    SQLLEN		    nIndicatorType;
    SQLLEN		    nIndicatorRemarks;
    	//classTable      *pTable = NULL;
    int tablenum=0;
	// CREATE A STATEMENT
    ODBC_CONN *han = (ODBC_CONN *) handle;
	
	V_OD_erg=SQLAllocHandle(SQL_HANDLE_STMT, han->V_OD_hdbc, &hstmt);
	
	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
    	{
    		return V_OD_erg ;
	}
    
    
    
    
   SQLNumResultCols(result.V_OD_hstmt,&V_OD_colanz);
  //printf("filed_index %s\n",name);
  
  for (field = 0; field < V_OD_colanz; field++) {
  	SQLDescribeCol(result.V_OD_hstmt, field + 1, colname, sizeof(colname),&colnamelen, \
&coltype, &precision, &scale, NULL);  //	printf("Field index  -- nome richiesto : %s, \
nome colonna : %s, id : %u\n",name,colname,field);  
	if  (strcmp(field,colname)==0){
  		SQLFreeHandle( hstmt, SQL_DROP );
		return TRUE;
  	}
	
  }
  SQLFreeHandle( hstmt, SQL_DROP );
  return FALSE;
//}
   
}


/*****************************************************************************

  field_list()

  Returns an array containing the name of each field in a given table

  <handle> is the database handle.
  <table> is the table name.
  <fields> points to a variable that will receive the char* array.

  This function returns the number of fields, or -1 if the command has
  failed.

  Be careful: <fields> can be NULL, so that just the count is returned.

*****************************************************************************/

static long field_list(DB_DATABASE handle, char *table, char ***fields)
{
  
    SQLCHAR         	colname[32];
    SQLSMALLINT     	coltype;
    SQLSMALLINT     	colnamelen;
    SQLUINTEGER     	precision;
    SQLSMALLINT     	scale;
    SQLSMALLINT         V_OD_colanz;
    ODBC_TABLES     	tablelist,*curtable;
    ODBC_RESULT     	result;
    SQLHSTMT        	hstmt;
    SQLRETURN		V_OD_erg,nReturn    = -1;
    SQLCHAR         	szTableName[101]    = "";
    SQLCHAR         	szTableType[101]    = "";
    SQLCHAR         	szTableRemarks[301] = "";
    SQLLEN		nIndicatorName;
    SQLLEN		nIndicatorType;
    SQLLEN		nIndicatorRemarks;
    int 		tablenum=0;
    int 		i ;
    int 		field;
    ODBC_CONN *han = (ODBC_CONN *) handle;	
	// CREATE A STATEMENT
	
	
	V_OD_erg=SQLAllocHandle(SQL_HANDLE_STMT, (ODBC_CONN *)han->V_OD_hdbc, &hstmt);
	
	if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
    	{
    		return V_OD_erg ;
	}
    
    
    
    
   SQLNumResultCols(result.V_OD_hstmt,&V_OD_colanz);
  //printf("filed_index %s\n",name);
  
  if (V_OD_colanz) {
  	GB.NewArray(fields, sizeof(char *), V_OD_colanz);
  	for (i = 0; i < V_OD_colanz; i++) {
  		SQLDescribeCol(result.V_OD_hstmt, i + 1, colname, sizeof(colname),&colnamelen, \
&coltype, &precision, &scale, NULL);  GB.NewString(&((*fields)[i]), colname,0);
	
  	}
  }
  
  SQLFreeHandle( hstmt, SQL_DROP );
  return (V_OD_colanz);
  
  
  
  
  
}


/*****************************************************************************

  field_info()

  Get field description

  <handle> is the database handle.
  <table> is the table name.
  <field> is the field name.
  <info> points to a structure filled by the function.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int field_info(DB_DATABASE handle, char *table, char *field, DB_FIELD *info)
{
  


/****** da postgres per copia esempio 
const char *query =
    "select pg_attribute.attname, pg_attribute.atttypid::int, "
    "pg_attribute.atttypmod, pg_attribute.attnotnull, pg_attrdef.adsrc "
    "from pg_class, pg_attribute "
    "left join pg_attrdef on (pg_attrdef.adrelid = pg_attribute.attrelid and \
pg_attrdef.adnum = pg_attribute.attnum) "  "where pg_class.relname = lower('&1') "
    "and pg_attribute.attname = lower('&2') "
    "and pg_attribute.attnum > 0 "
    "and pg_attribute.attrelid = pg_class.oid";

  PGresult *res;
  Oid type;
  GB_VARIANT def;
  char *val;

  if (do_query((PGconn *)handle, "Unable to get field info: &1", &res, query, 2, \
table, field))  return TRUE;

  if (PQntuples(res) != 1)
  {
    GB.Error("Unable to find field &1.&2", table, field);
    return TRUE;
  }

  info->name = NULL;

  type = atoi(PQgetvalue(res, 0, 1));
  info->type = conv_type(type);

  info->length = 0;
  if (info->type == GB_T_STRING)
  {
    info->length = atoi(PQgetvalue(res, 0, 2));
    if (info->length < 0)
      info->length = 0;
    else
      info->length -= 4;
  }

  info->def._object.type = GB_T_NULL;

  if (conv_boolean(PQgetvalue(res, 0, 3)))
  {
    def.type = GB_T_VARIANT;
    def.value._object.type = GB_T_NULL;

    val = PQgetvalue(res, 0, 4);
    if (val && *val)
    {
      switch(type)
      {
        case GB_T_BOOLEAN:
          def.value._boolean.value = (val[1] == 't');
          def.value._boolean.type = GB_T_BOOLEAN;
          break;

        default:
          conv_data(unquote(val), &def.value, type);
      }

      GB.StoreVariant(&def, &info->def);
    }
  }

  PQclear(res);
  return FALSE;

***** da postgres per esempio end ************/


}


/*****************************************************************************

  index_exist()

  Returns if an index exists in a given table

  <handle> is the database handle.
  <table> is the table name.
  <field> is the index name.

  This function returns TRUE if the index exists, and FALSE if not.

*****************************************************************************/

static int index_exist(DB_DATABASE handle, char *table, char *index)
{
  //printf("qui24\n"); 
}


/*****************************************************************************

  index_list()

  Returns an array containing the name of each index in a given table

  <handle> is the database handle.
  <table> is the table name.
  <indexes> points to a variable that will receive the char* array.

  This function returns the number of indexes, or -1 if the command has
  failed.

  Be careful: <indexes> can be NULL, so that just the count is returned.

*****************************************************************************/

static long index_list(DB_DATABASE handle, char *table, char ***indexes)
{
  //printf("qui25\n"); 
}


/*****************************************************************************

  index_info()

  Get index description

  <handle> is the database handle.
  <table> is the table name.
  <field> is the index name.
  <info> points to a structure filled by the function.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int index_info(DB_DATABASE handle, char *table, char *index, DB_INDEX *info)
{
 //printf("qui26\n");  
}


/*****************************************************************************

  index_delete()

  Deletes an index.

  <handle> is the database handle.
  <table> is the table name.
  <index> is the index name.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int index_delete(DB_DATABASE handle, char *table, char *index)
{
//  printf("qui27\n"); 
}


/*****************************************************************************

  index_create()

  Creates an index.

  <handle> is the database handle.
  <table> is the table name.
  <index> is the index name.
  <info> points to a structure describing the index.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int index_create(DB_DATABASE handle, char *table, char *index, DB_INDEX *info)
{
//  printf("qui28\n"); 
}


/*****************************************************************************

  database_exist()

  Returns if a database exists

  <handle> is any database handle.
  <name> is the database name.

  This function returns TRUE if the database exists, and FALSE if not.

*****************************************************************************/

static int database_exist(DB_DATABASE handle, char *name)
{
  //printf("qui29\n"); 
}



/*****************************************************************************

  database_list()

  Returns an array containing the name of each database

  <handle> is any database handle.
  <databases> points to a variable that will receive the char* array.

  This function returns the number of databases, or -1 if the command has
  failed.

  Be careful: <databases> can be NULL, so that just the count is returned.

*****************************************************************************/

static long database_list(DB_DATABASE handle, char ***databases)
{

/* da finire 
SQLRETURN cliRC = SQL_SUCCESS;
  int rc = 0;
  SQLCHAR dbAliasBuf[SQL_MAX_DSN_LENGTH + 1];
  SQLCHAR dbCommentBuf[255];
  SQLSMALLINT aliasLen, commentLen;

  

  // get list of data sources
  cliRC = SQLDataSources(handle,
                         SQL_FETCH_FIRST,
                         dbAliasBuf,
                         SQL_MAX_DSN_LENGTH + 1,
                         &aliasLen,
                         dbCommentBuf,
                         255,
                         &commentLen);
  ENV_HANDLE_CHECK(henv, cliRC);

  while (cliRC != SQL_NO_DATA_FOUND)
  {
    printf("  %-17s %s\n", dbAliasBuf, dbCommentBuf);

    // get list of data sources 
    cliRC = SQLDataSources(handle,
                           SQL_FETCH_NEXT,
                           dbAliasBuf,
                           SQL_MAX_DSN_LENGTH + 1,
                           &aliasLen,
                           dbCommentBuf,
                           255,
                           &commentLen);
    ENV_HANDLE_CHECK(handle, cliRC);
  }



*/

  //printf("qui30\n"); 
}


/*****************************************************************************

  database_is_system()

  Returns if a database is a system database.

  <handle> is any database handle.
  <name> is the database name.

  This function returns TRUE if the database is a system database, and
  FALSE if not.

*****************************************************************************/

static int database_is_system(DB_DATABASE handle, char *name)
{
  //printf("qui31\n"); 
}

/*****************************************************************************

  table_type()
  Not Valid in postgresql

  <handle> is the database handle.
  <table> is the table name.
*****************************************************************************/
static char *table_type(DB_DATABASE handle, char *table, char *type)
{
  if (type)
    GB.Error("ODBC does not have any table types");
  return NULL;
}

/*****************************************************************************

  database_delete()

  Deletes a database.

  <handle> is the database handle.
  <name> is the database name.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int database_delete(DB_DATABASE handle, char *name)
{
    GB.Error("ODBC does not implement this function");
  return TRUE; 
}


/*****************************************************************************

  database_create()

  Creates a database.

  <handle> is the database handle.
  <name> is the database name.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int database_create(DB_DATABASE handle, char *name)
{
   GB.Error("ODBC does not implement this function");
  return TRUE;
}


/*****************************************************************************

  user_exist()

  Returns if a user exists.

  <handle> is any database handle.
  <name> is the user name.

  This function returns TRUE if the user exists, and FALSE if not.

*****************************************************************************/

static int user_exist(DB_DATABASE handle, char *name)
{
  GB.Error("ODBC does not implement this function");
  return  ; 
}


/*****************************************************************************

  user_list()

  Returns an array containing the name of each user.

  <handle> is the database handle.
  <users> points to a variable that will receive the char* array.

  This function returns the number of users, or -1 if the command has
  failed.

  Be careful: <users> can be NULL, so that just the count is returned.

*****************************************************************************/

static long user_list(DB_DATABASE handle, char ***users)
{
  GB.Error("ODBC does not implement this function");
  return (-1) ; 
}


/*****************************************************************************

  user_info()

  Get user description

  <handle> is the database handle.
  <name> is the user name.
  <info> points to a structure filled by the function.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int user_info(DB_DATABASE handle, char *name, DB_USER *info)
{
   GB.Error("ODBC does not implement this function");
  return TRUE ;  
}


/*****************************************************************************

  user_delete()

  Deletes a user.

  <handle> is any database handle.
  <name> is the user name.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int user_delete(DB_DATABASE handle, char *name)
{
 GB.Error("ODBC can't delete users");
  return TRUE ;  
}


/*****************************************************************************

  user_create()

  Creates a user.

  <handle> is the database handle.
  <name> is the user name.
  <info> points to a structure describing the user.

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int user_create(DB_DATABASE handle, char *name, DB_USER *info)
{
  GB.Error("ODBC can't create users");
  return TRUE ;  
}


/*****************************************************************************

  user_set_password()

  Change the user password.

  <handle> is the database handle.
  <name> is the user name.
  <password> is the new password

  This function returns TRUE if the command has failed, and FALSE if
  everything was OK.

*****************************************************************************/

static int user_set_password(DB_DATABASE handle, char *name, char *password)
{
 GB.Error("ODBC can't set user's password");
  return TRUE ;  
}

/*****************************************************************************

  The driver interface

*****************************************************************************/

static DB_DRIVER _driver =
{
  "odbc",
  (void *)open_database,
  (void *)close_database,
  (void *)format_value,
  (void *)exec_query,
  (void *)begin_transaction,
  (void *)commit_transaction,
  (void *)rollback_transaction,
  (void *)get_quote,
  {
    (void *)query_init,
    (void *)query_fill,
    (void *)query_release,
    {
      (void *)field_type,
      (void *)field_name,
      (void *)field_index,
      (void *)field_length,
    },
  },
 // /* 
 {
    (void *)field_exist,
    (void *)field_list,
    (void *)field_info,
  },
  //*/
  ///*
  {
    (void *)table_init,
    (void *)table_index,
    (void *)table_release,
    (void *)table_exist,
    (void *)table_list,
    (void *)table_primary_key,
    (void *)table_is_system,
    (void *)table_type,
    (void *)table_delete,
    (void *)table_create,
  },
  {
    (void *)index_exist,
    (void *)index_list,
    (void *)index_info,
    (void *)index_delete,
    (void *)index_create,
  },
  {
    (void *)database_exist,
    (void *)database_list,
    (void *)database_is_system,
    (void *)database_delete,
    (void *)database_create,
  },
  {
    (void *)user_exist,
    (void *)user_list,
    (void *)user_info,
    (void *)user_delete,
    (void *)user_create,
    (void *)user_set_password
  }
  //*/
};


/*****************************************************************************

  The component entry and exit functions.

*****************************************************************************/

int GB_INIT(void)
{
  GB.GetInterface("gb.db", DB_INTERFACE_VERSION, &DB);
  DB.Register(&_driver);

  return -1;
}

void GB_EXIT()
{
}


["main.h" (text/x-c-header)]

/***************************************************************************

  main.h

  PostgreSQL driver

  (c) 2000-2003 Beno� Minisini <gambas@users.sourceforge.net>

  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 1, 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; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

***************************************************************************/

#ifndef __MAIN_H
#define __MAIN_H

#include "gambas.h"
#include "gb_common.h"
#include "../gb.db.h"

#ifndef __MAIN_C
extern GB_INTERFACE GB;
extern DB_INTERFACE DB;
#endif

#define QUOTE_STRING ""

#endif /* __MAIN_H */

-------------------------------------------------------
This SF.Net email is sponsored by: IntelliVIEW -- Interactive Reporting
Tool for open source databases. Create drag-&-drop reports. Save time
by over 75%! Publish reports on the web. Export to DOC, XLS, RTF, etc.
Download a FREE copy at http://www.intelliview.com/go/osdn_nl
_______________________________________________
Gambas-devel mailing list
Gambas-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/gambas-devel

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic