@ -24,6 +24,8 @@
# include <ecpglib.h>
# include <sqlca.h>
extern int no_auto_trans ;
static PGconn * simple_connection = NULL ;
static int simple_debug = 0 ;
static FILE * debugstream = NULL ;
@ -80,6 +82,11 @@ ECPGdo(int lineno, char *query,...)
PGresult * results ;
PGnotify * notify ;
enum ECPGttype type ;
void * value = NULL , * ind_value ;
long varcharsize , ind_varcharsize ;
long arrsize , ind_arrsize ;
long offset , ind_offset ;
enum ECPGttype ind_type ;
va_start ( ap , query ) ;
@ -96,12 +103,6 @@ ECPGdo(int lineno, char *query,...)
*/
while ( type ! = ECPGt_EOIT )
{
void * value = NULL , * ind_value ;
long varcharsize , ind_varcharsize ;
long size , ind_size ;
long arrsize , ind_arrsize ;
enum ECPGttype ind_type ;
char * newcopy ;
char * mallocedval = NULL ;
char * tobeinserted = NULL ;
@ -116,13 +117,13 @@ ECPGdo(int lineno, char *query,...)
value = va_arg ( ap , void * ) ;
varcharsize = va_arg ( ap , long ) ;
size = va_arg ( ap , long ) ;
arrsize = va_arg ( ap , long ) ;
offset = va_arg ( ap , long ) ;
ind_type = va_arg ( ap , enum ECPGttype ) ;
ind_value = va_arg ( ap , void * ) ;
ind_varcharsize = va_arg ( ap , long ) ;
ind_size = va_arg ( ap , long ) ;
ind_arrsize = va_arg ( ap , long ) ;
ind_offset = va_arg ( ap , long ) ;
buff [ 0 ] = ' \0 ' ;
@ -211,7 +212,6 @@ ECPGdo(int lineno, char *query,...)
break ;
case ECPGt_varchar :
case ECPGt_varchar2 :
{
struct ECPGgeneric_varchar * var =
( struct ECPGgeneric_varchar * ) value ;
@ -233,7 +233,7 @@ ECPGdo(int lineno, char *query,...)
default :
/* Not implemented yet */
register_error ( - 1 , " Unsupported type %s on line %d. " ,
register_error ( ECPG_UNSUPPORTED , " Unsupported type %s on line %d. " ,
ECPGtype_name ( type ) , lineno ) ;
return false ;
break ;
@ -257,7 +257,7 @@ ECPGdo(int lineno, char *query,...)
* We have an argument but we dont have the matched up string
* in the string
*/
register_error ( - 1 , " Too many arguments line %d. " , lineno ) ;
register_error ( ECPG_TOO_MANY_ARGUMENTS , " Too many arguments line %d. " , lineno ) ;
return false ;
}
else
@ -293,17 +293,17 @@ ECPGdo(int lineno, char *query,...)
/* Check if there are unmatched things left. */
if ( strstr ( copiedquery , " ;; " ) ! = NULL )
{
register_error ( - 1 , " Too few arguments line %d. " , lineno ) ;
register_error ( ECPG_TOO_FEW_ARGUMENTS , " Too few arguments line %d. " , lineno ) ;
return false ;
}
/* Now the request is built. */
if ( committed )
if ( committed & & ! no_auto_trans )
{
if ( ( results = PQexec ( simple_connection , " begin transaction " ) ) = = NULL )
{
register_error ( - 1 , " Error starting transaction line %d. " , lineno ) ;
register_error ( ECPG_TRANS , " Error starting transaction line %d. " , lineno ) ;
return false ;
}
PQclear ( results ) ;
@ -318,15 +318,15 @@ ECPGdo(int lineno, char *query,...)
{
ECPGlog ( " ECPGdo line %d: error: %s " , lineno ,
PQerrorMessage ( simple_connection ) ) ;
register_error ( - 1 , " Postgres error: %s line %d. " ,
register_error ( ECPG_PGSQL , " Postgres error: %s line %d. " ,
PQerrorMessage ( simple_connection ) , lineno ) ;
}
else
{
sqlca . sqlerrd [ 2 ] = 0 ;
switch ( PQresultStatus ( results ) )
{
int m ,
n ,
x ;
int nfields , ntuples , act_tuple , act_field ;
case PGRES_TUPLES_OK :
@ -336,306 +336,308 @@ ECPGdo(int lineno, char *query,...)
* ! !
*/
m = PQnfields ( results ) ;
n = PQntuples ( results ) ;
if ( n < 1 )
nfields = PQnfields ( results ) ;
sqlca . sqlerrd [ 2 ] = ntuples = PQntuples ( results ) ;
status = true ;
if ( ntuples < 1 )
{
ECPGlog ( " ECPGdo line %d: Incorrect number of matches: %d \n " ,
lineno , n ) ;
register_error ( 1 , " Data not found line %d. " , lineno ) ;
lineno , ntuples ) ;
register_error ( ECPG_NOT_FOUND , " Data not found line %d. " , lineno ) ;
status = false ;
break ;
}
if ( n > 1 )
{
ECPGlog ( " ECPGdo line %d: Incorrect number of matches: %d \n " ,
lineno , n ) ;
register_error ( - 1 , " To many matches line %d. " , lineno ) ;
break ;
}
status = true ;
for ( x = 0 ; x < m & & status ; x + + )
{
void * value = NULL , * ind_value ;
long varcharsize , ind_varcharsize ;
long size , ind_size ;
long arrsize , ind_arrsize ;
enum ECPGttype ind_type ;
char * pval = PQgetvalue ( results , 0 , x ) ;
/*
* long int * res_int ; char * * res_charstar ; char *
* res_char ; int res_len ;
*/
char * scan_length ;
ECPGlog ( " ECPGdo line %d: RESULT: %s \n " , lineno , pval ? pval : " " ) ;
/* Now the pval is a pointer to the value. */
/* We will have to decode the value */
type = va_arg ( ap , enum ECPGttype ) ;
value = va_arg ( ap , void * ) ;
varcharsize = va_arg ( ap , long ) ;
size = va_arg ( ap , long ) ;
arrsize = va_arg ( ap , long ) ;
ind_type = va_arg ( ap , enum ECPGttype ) ;
ind_value = va_arg ( ap , void * ) ;
ind_varcharsize = va_arg ( ap , long ) ;
ind_size = va_arg ( ap , long ) ;
ind_arrsize = va_arg ( ap , long ) ;
/* check for null value and set indicator accordingly */
switch ( ind_type )
{
case ECPGt_short :
case ECPGt_unsigned_short :
* ( short * ) ind_value = - PQgetisnull ( results , 0 , x ) ;
break ;
case ECPGt_int :
case ECPGt_unsigned_int :
* ( int * ) ind_value = - PQgetisnull ( results , 0 , x ) ;
break ;
case ECPGt_long :
case ECPGt_unsigned_long :
* ( long * ) ind_value = - PQgetisnull ( results , 0 , x ) ;
break ;
default :
break ;
}
switch ( type )
{
long res ;
unsigned long ures ;
double dres ;
case ECPGt_short :
case ECPGt_int :
case ECPGt_long :
if ( pval )
{
res = strtol ( pval , & scan_length , 10 ) ;
if ( * scan_length ! = ' \0 ' ) /* Garbage left */
{
register_error ( - 1 , " Not correctly formatted int type: %s line %d. " ,
pval , lineno ) ;
status = false ;
res = 0L ;
}
}
else
res = 0L ;
/* Again?! Yes */
switch ( type )
{
case ECPGt_short :
* ( short * ) value = ( short ) res ;
break ;
case ECPGt_int :
* ( int * ) value = ( int ) res ;
break ;
case ECPGt_long :
* ( long * ) value = res ;
break ;
default :
/* Cannot happen */
break ;
}
break ;
case ECPGt_unsigned_short :
case ECPGt_unsigned_int :
case ECPGt_unsigned_long :
if ( pval )
{
ures = strtoul ( pval , & scan_length , 10 ) ;
if ( * scan_length ! = ' \0 ' ) /* Garbage left */
{
register_error ( - 1 , " Not correctly formatted unsigned type: %s line %d. " ,
pval , lineno ) ;
status = false ;
ures = 0L ;
}
}
else
ures = 0L ;
/* Again?! Yes */
switch ( type )
{
case ECPGt_unsigned_short :
* ( unsigned short * ) value = ( unsigned short ) ures ;
break ;
case ECPGt_unsigned_int :
* ( unsigned int * ) value = ( unsigned int ) ures ;
break ;
case ECPGt_unsigned_long :
* ( unsigned long * ) value = ures ;
break ;
default :
/* Cannot happen */
break ;
}
break ;
case ECPGt_float :
case ECPGt_double :
if ( pval )
{
dres = strtod ( pval , & scan_length ) ;
if ( * scan_length ! = ' \0 ' ) /* Garbage left */
{
register_error ( - 1 , " Not correctly formatted floating point type: %s line %d. " ,
pval , lineno ) ;
status = false ;
dres = 0.0 ;
}
}
else
dres = 0.0 ;
/* Again?! Yes */
switch ( type )
{
case ECPGt_float :
* ( float * ) value = dres ;
break ;
case ECPGt_double :
* ( double * ) value = dres ;
break ;
default :
/* Cannot happen */
break ;
}
break ;
case ECPGt_bool :
if ( pval )
{
if ( pval [ 0 ] = = ' f ' & & pval [ 1 ] = = ' \0 ' )
{
* ( char * ) value = false ;
break ;
}
else if ( pval [ 0 ] = = ' t ' & & pval [ 1 ] = = ' \0 ' )
{
* ( char * ) value = true ;
break ;
}
}
register_error ( - 1 , " Unable to convert %s to bool on line %d. " ,
( pval ? pval : " NULL " ) ,
lineno ) ;
return false ;
break ;
case ECPGt_char :
case ECPGt_unsigned_char :
{
if ( varcharsize = = 0 )
{
/* char* */
strncpy ( ( char * ) value , pval , strlen ( pval ) ) ;
( ( char * ) value ) [ strlen ( pval ) ] = ' \0 ' ;
}
else
{
strncpy ( ( char * ) value , pval , varcharsize ) ;
if ( varcharsize < strlen ( pval ) )
{
/* truncation */
switch ( ind_type )
{
case ECPGt_short :
case ECPGt_unsigned_short :
* ( short * ) ind_value = varcharsize ;
break ;
case ECPGt_int :
case ECPGt_unsigned_int :
* ( int * ) ind_value = varcharsize ;
break ;
case ECPGt_long :
case ECPGt_unsigned_long :
* ( long * ) ind_value = varcharsize ;
break ;
default :
break ;
}
}
}
}
break ;
case ECPGt_varchar :
{
struct ECPGgeneric_varchar * var =
( struct ECPGgeneric_varchar * ) value ;
strncpy ( var - > arr , pval , varcharsize ) ;
var - > len = strlen ( pval ) ;
if ( var - > len > varcharsize )
{
/* truncation */
switch ( ind_type )
{
case ECPGt_short :
case ECPGt_unsigned_short :
* ( short * ) ind_value = varcharsize ;
break ;
case ECPGt_int :
case ECPGt_unsigned_int :
* ( int * ) ind_value = varcharsize ;
break ;
case ECPGt_long :
case ECPGt_unsigned_long :
* ( long * ) ind_value = varcharsize ;
break ;
default :
break ;
}
var - > len = varcharsize ;
}
}
break ;
case ECPGt_EORT :
ECPGlog ( " ECPGdo line %d: Too few arguments. \n " , lineno ) ;
register_error ( - 1 , " Too few arguments line %d. " , lineno ) ;
status = false ;
break ;
default :
register_error ( - 1 , " Unsupported type %s on line %d. " ,
ECPGtype_name ( type ) , lineno ) ;
return false ;
break ;
}
for ( act_field = 0 ; act_field < nfields & & status ; act_field + + )
{
char * pval ;
char * scan_length ;
type = va_arg ( ap , enum ECPGttype ) ;
value = va_arg ( ap , void * ) ;
varcharsize = va_arg ( ap , long ) ;
arrsize = va_arg ( ap , long ) ;
offset = va_arg ( ap , long ) ;
ind_type = va_arg ( ap , enum ECPGttype ) ;
ind_value = va_arg ( ap , void * ) ;
ind_varcharsize = va_arg ( ap , long ) ;
ind_arrsize = va_arg ( ap , long ) ;
ind_offset = va_arg ( ap , long ) ;
/* if we don't have enough space, we cannot read all tuples */
if ( ( arrsize > 0 & & ntuples > arrsize ) | | ( ind_arrsize > 0 & & ntuples > ind_arrsize ) )
{
ECPGlog ( " ECPGdo line %d: Incorrect number of matches: %d don't fit into array of %d \n " ,
lineno , ntuples , arrsize ) ;
register_error ( ECPG_TOO_MANY_MATCHES , " Too many matches line %d. " , lineno ) ;
status = false ;
break ;
}
for ( act_tuple = 0 ; act_tuple < ntuples ; act_tuple + + )
{
pval = PQgetvalue ( results , act_tuple , act_field ) ;
ECPGlog ( " ECPGdo line %d: RESULT: %s \n " , lineno , pval ? pval : " " ) ;
/* Now the pval is a pointer to the value. */
/* We will have to decode the value */
/* check for null value and set indicator accordingly */
switch ( ind_type )
{
case ECPGt_short :
case ECPGt_unsigned_short :
( ( short * ) ind_value ) [ act_tuple ] = - PQgetisnull ( results , act_tuple , act_field ) ;
break ;
case ECPGt_int :
case ECPGt_unsigned_int :
( ( int * ) ind_value ) [ act_tuple ] = - PQgetisnull ( results , act_tuple , act_field ) ;
break ;
case ECPGt_long :
case ECPGt_unsigned_long :
( ( long * ) ind_value ) [ act_tuple ] = - PQgetisnull ( results , act_tuple , act_field ) ;
break ;
default :
break ;
}
switch ( type )
{
long res ;
unsigned long ures ;
double dres ;
case ECPGt_short :
case ECPGt_int :
case ECPGt_long :
if ( pval )
{
res = strtol ( pval , & scan_length , 10 ) ;
if ( * scan_length ! = ' \0 ' ) /* Garbage left */
{
register_error ( ECPG_INT_FORMAT , " Not correctly formatted int type: %s line %d. " ,
pval , lineno ) ;
status = false ;
res = 0L ;
}
}
else
res = 0L ;
/* Again?! Yes */
switch ( type )
{
case ECPGt_short :
( ( short * ) value ) [ act_tuple ] = ( short ) res ;
break ;
case ECPGt_int :
( ( int * ) value ) [ act_tuple ] = ( int ) res ;
break ;
case ECPGt_long :
( ( long * ) value ) [ act_tuple ] = res ;
break ;
default :
/* Cannot happen */
break ;
}
break ;
case ECPGt_unsigned_short :
case ECPGt_unsigned_int :
case ECPGt_unsigned_long :
if ( pval )
{
ures = strtoul ( pval , & scan_length , 10 ) ;
if ( * scan_length ! = ' \0 ' ) /* Garbage left */
{
register_error ( ECPG_UINT_FORMAT , " Not correctly formatted unsigned type: %s line %d. " ,
pval , lineno ) ;
status = false ;
ures = 0L ;
}
}
else
ures = 0L ;
/* Again?! Yes */
switch ( type )
{
case ECPGt_unsigned_short :
( ( unsigned short * ) value ) [ act_tuple ] = ( unsigned short ) ures ;
break ;
case ECPGt_unsigned_int :
( ( unsigned int * ) value ) [ act_tuple ] = ( unsigned int ) ures ;
break ;
case ECPGt_unsigned_long :
( ( unsigned long * ) value ) [ act_tuple ] = ures ;
break ;
default :
/* Cannot happen */
break ;
}
break ;
case ECPGt_float :
case ECPGt_double :
if ( pval )
{
dres = strtod ( pval , & scan_length ) ;
if ( * scan_length ! = ' \0 ' ) /* Garbage left */
{
register_error ( ECPG_FLOAT_FORMAT , " Not correctly formatted floating point type: %s line %d. " ,
pval , lineno ) ;
status = false ;
dres = 0.0 ;
}
}
else
dres = 0.0 ;
/* Again?! Yes */
switch ( type )
{
case ECPGt_float :
( ( float * ) value ) [ act_tuple ] = dres ;
break ;
case ECPGt_double :
( ( double * ) value ) [ act_tuple ] = dres ;
break ;
default :
/* Cannot happen */
break ;
}
break ;
case ECPGt_bool :
if ( pval )
{
if ( pval [ 0 ] = = ' f ' & & pval [ 1 ] = = ' \0 ' )
{
( ( char * ) value ) [ act_tuple ] = false ;
break ;
}
else if ( pval [ 0 ] = = ' t ' & & pval [ 1 ] = = ' \0 ' )
{
( ( char * ) value ) [ act_tuple ] = true ;
break ;
}
}
register_error ( ECPG_CONVERT_BOOL , " Unable to convert %s to bool on line %d. " ,
( pval ? pval : " NULL " ) ,
lineno ) ;
status = false ;
break ;
case ECPGt_char :
case ECPGt_unsigned_char :
{
if ( varcharsize = = 0 )
{
/* char* */
strncpy ( ( ( char * * ) value ) [ act_tuple ] , pval , strlen ( pval ) ) ;
( ( ( char * * ) value ) [ act_tuple ] ) [ strlen ( pval ) ] = ' \0 ' ;
}
else
{
strncpy ( ( char * ) ( value + offset * act_tuple ) , pval , varcharsize ) ;
if ( varcharsize < strlen ( pval ) )
{
/* truncation */
switch ( ind_type )
{
case ECPGt_short :
case ECPGt_unsigned_short :
( ( short * ) ind_value ) [ act_tuple ] = varcharsize ;
break ;
case ECPGt_int :
case ECPGt_unsigned_int :
( ( int * ) ind_value ) [ act_tuple ] = varcharsize ;
break ;
case ECPGt_long :
case ECPGt_unsigned_long :
( ( long * ) ind_value ) [ act_tuple ] = varcharsize ;
break ;
default :
break ;
}
}
}
}
break ;
case ECPGt_varchar :
{
struct ECPGgeneric_varchar * var =
( struct ECPGgeneric_varchar * ) ( value + offset * act_tuple ) ;
if ( varcharsize = = 0 )
strncpy ( var - > arr , pval , strlen ( pval ) ) ;
else
strncpy ( var - > arr , pval , varcharsize ) ;
var - > len = strlen ( pval ) ;
if ( varcharsize > 0 & & var - > len > varcharsize )
{
/* truncation */
switch ( ind_type )
{
case ECPGt_short :
case ECPGt_unsigned_short :
( ( short * ) ind_value ) [ act_tuple ] = varcharsize ;
break ;
case ECPGt_int :
case ECPGt_unsigned_int :
( ( int * ) ind_value ) [ act_tuple ] = varcharsize ;
break ;
case ECPGt_long :
case ECPGt_unsigned_long :
( ( long * ) ind_value ) [ act_tuple ] = varcharsize ;
break ;
default :
break ;
}
var - > len = varcharsize ;
}
}
break ;
case ECPGt_EORT :
ECPGlog ( " ECPGdo line %d: Too few arguments. \n " , lineno ) ;
register_error ( ECPG_TOO_FEW_ARGUMENTS , " Too few arguments line %d. " , lineno ) ;
status = false ;
break ;
default :
register_error ( ECPG_UNSUPPORTED , " Unsupported type %s on line %d. " ,
ECPGtype_name ( type ) , lineno ) ;
status = false ;
break ;
}
}
}
type = va_arg ( ap , enum ECPGttype ) ;
if ( status & & type ! = ECPGt_EORT )
{
register_error ( - 1 , " Too many arguments line %d. " , lineno ) ;
return false ;
register_error ( ECPG_TOO_MANY_ARGUMENTS , " Too many arguments line %d. " , lineno ) ;
status = false ;
}
PQclear ( results ) ;
break ;
case PGRES_EMPTY_QUERY :
/* do nothing */
register_error ( - 1 , " Empty query line %d. " , lineno ) ;
register_error ( ECPG_EMPTY , " Empty query line %d. " , lineno ) ;
break ;
case PGRES_COMMAND_OK :
status = true ;
sqlca . sqlerrd [ 2 ] = atol ( PQcmdTuples ( results ) ) ;
ECPGlog ( " TEST: %s \n " , PQcmdTuples ( results ) ) ;
ECPGlog ( " ECPGdo line %d Ok: %s \n " , lineno , PQcmdStatus ( results ) ) ;
break ;
case PGRES_NONFATAL_ERROR :
@ -643,8 +645,9 @@ ECPGdo(int lineno, char *query,...)
case PGRES_BAD_RESPONSE :
ECPGlog ( " ECPGdo line %d: Error: %s " ,
lineno , PQerrorMessage ( simple_connection ) ) ;
register_error ( - 1 , " Error: %s line %d. " ,
register_error ( ECPG_PGSQL , " Error: %s line %d. " ,
PQerrorMessage ( simple_connection ) , lineno ) ;
status = false ;
break ;
case PGRES_COPY_OUT :
ECPGlog ( " ECPGdo line %d: Got PGRES_COPY_OUT ... tossing. \n " , lineno ) ;
@ -657,9 +660,11 @@ ECPGdo(int lineno, char *query,...)
default :
ECPGlog ( " ECPGdo line %d: Got something else, postgres error. \n " ,
lineno ) ;
register_error ( - 1 , " Postgres error line %d. " , lineno ) ;
register_error ( ECPG_PGSQL , " Postgres error line %d. " , lineno ) ;
status = false ;
break ;
}
}
/* check for asynchronous returns */
notify = PQnotifies ( simple_connection ) ;
@ -683,11 +688,12 @@ ECPGtrans(int lineno, const char * transaction)
ECPGlog ( " ECPGtrans line %d action = %s \n " , lineno , transaction ) ;
if ( ( res = PQexec ( simple_connection , transaction ) ) = = NULL )
{
register_error ( - 1 , " Error in transaction processing line %d. " , lineno ) ;
register_error ( ECPG_TRANS , " Error in transaction processing line %d. " , lineno ) ;
return ( FALSE ) ;
}
PQclear ( res ) ;
committed = 1 ;
if ( strcmp ( transaction , " commit " ) = = 0 | | strcmp ( transaction , " rollback " ) = = 0 )
committed = 1 ;
return ( TRUE ) ;
}
@ -716,21 +722,25 @@ ECPGconnect(const char *dbname)
if ( PQstatus ( simple_connection ) = = CONNECTION_BAD )
{
ECPGfinish ( ) ;
ECPGlog ( " ECPG connect: could not open database %s\n " , dbname ) ;
register_error ( - 1 , " ECPG connect: could not open database %s." , dbname ) ;
ECPGlog ( " connect: could not open database %s \n " , dbname ) ;
register_error ( ECPG_CONNECT , " connect: could not open database %s. " , dbname ) ;
return false ;
}
return true ;
}
bool
ECPGstatus ( void )
ECPGdisconnect ( const char * dbname )
{
return PQstatus ( simple_connection ) ! = CONNECTION_BAD ;
if ( strlen ( dbname ) > 0 & & strcmp ( PQdb ( simple_connection ) , dbname ) ! = 0 )
{
ECPGlog ( " disconnect: not connected to database %s \n " , dbname ) ;
register_error ( ECPG_DISCONNECT , " disconnect: not connected to database %s. " , dbname ) ;
return false ;
}
return ECPGfinish ( ) ;
}
bool
ECPGfinish ( void )
{