@@ -64,6 +64,7 @@ struct variable
6464{
6565enum ECPGttype type ;
6666void * value ;
67+ void * pointer ;
6768long varcharsize ;
6869long arrsize ;
6970long offset ;
@@ -91,19 +92,38 @@ struct prepared_statement
9192struct prepared_statement * next ;
9293}* prep_stmts = NULL ;
9394
95+ struct auto_mem
96+ {
97+ void * pointer ;
98+ struct auto_mem * next ;
99+ }* auto_allocs = NULL ;
100+
94101static int simple_debug = 0 ;
95102static FILE * debugstream = NULL ;
96103
97104static void
98105register_error (long code ,char * fmt ,...)
99106{
100107va_list args ;
101-
108+ struct auto_mem * am ;
109+
102110sqlca .sqlcode = code ;
103111va_start (args ,fmt );
104112vsprintf (sqlca .sqlerrm .sqlerrmc ,fmt ,args );
105113va_end (args );
106114sqlca .sqlerrm .sqlerrml = strlen (sqlca .sqlerrm .sqlerrmc );
115+
116+ /* free all memory we allocate for the user */
117+ for (am = auto_allocs ;am ;)
118+ {
119+ struct auto_mem * act = am ;
120+
121+ am = am -> next ;
122+ free (act -> pointer );
123+ free (act );
124+ }
125+
126+ auto_allocs = NULL ;
107127}
108128
109129static struct connection *
@@ -166,7 +186,7 @@ ecpg_alloc(long size, int lineno)
166186register_error (ECPG_OUT_OF_MEMORY ,"out of memory in line %d" ,lineno );
167187return NULL ;
168188}
169-
189+
170190memset (new ,'\0' ,size );
171191return (new );
172192}
@@ -186,6 +206,15 @@ ecpg_strdup(const char *string, int lineno)
186206return (new );
187207}
188208
209+ static void
210+ add_mem (void * ptr ,int lineno )
211+ {
212+ struct auto_mem * am = (struct auto_mem * )ecpg_alloc (sizeof (struct auto_mem ),lineno );
213+
214+ am -> next = auto_allocs ;
215+ auto_allocs = am ;
216+ }
217+
189218/* This function returns a newly malloced string that has the ' and \
190219 in the argument quoted with \.
191220 */
@@ -301,26 +330,33 @@ create_statement(int lineno, struct connection *connection, struct statement **
301330return false;
302331
303332var -> type = type ;
304- var -> value = va_arg (ap ,void * );
333+ var -> pointer = va_arg (ap ,void * );
334+
335+ /* if variable is NULL, the statement hasn't been prepared */
336+ if (var -> pointer == NULL )
337+ {
338+ ECPGlog ("create_statement: invalid statement name\n" );
339+ register_error (ECPG_INVALID_STMT ,"Invalid statement name in line %d" ,lineno );
340+ free (var );
341+ return false;
342+ }
343+
305344var -> varcharsize = va_arg (ap ,long );
306345var -> arrsize = va_arg (ap ,long );
307346var -> offset = va_arg (ap ,long );
347+
348+ if (var -> arrsize == 0 || var -> varcharsize == 0 )
349+ var -> value = * ((void * * )(var -> pointer ));
350+ else
351+ var -> value = var -> pointer ;
352+
308353var -> ind_type = va_arg (ap ,enum ECPGttype );
309354var -> ind_value = va_arg (ap ,void * );
310355var -> ind_varcharsize = va_arg (ap ,long );
311356var -> ind_arrsize = va_arg (ap ,long );
312357var -> ind_offset = va_arg (ap ,long );
313358var -> next = NULL ;
314359
315- /* if variable is NULL, the statement hasn't been prepared */
316- if (var -> value == NULL )
317- {
318- ECPGlog ("create_statement: invalid statement name\n" );
319- register_error (ECPG_INVALID_STMT ,"Invalid statement name in line %d" ,lineno );
320- free (var );
321- return false;
322- }
323-
324360for (ptr = * list ;ptr && ptr -> next ;ptr = ptr -> next );
325361
326362if (ptr == NULL )
@@ -478,8 +514,7 @@ ECPGexecute(struct statement * stmt)
478514break ;
479515case ECPGt_char_variable :
480516{
481- /* set slen to string length if type is char * */
482- int slen = (var -> varcharsize == 0 ) ?strlen ((char * )var -> value ) :var -> varcharsize ;
517+ int slen = strlen ((char * )var -> value );
483518char * tmp ;
484519
485520if (!(newcopy = ecpg_alloc (slen + 1 ,stmt -> lineno )))
@@ -632,13 +667,6 @@ ECPGexecute(struct statement * stmt)
632667act_field ;
633668
634669case PGRES_TUPLES_OK :
635-
636- /*
637- * XXX Cheap Hack. For now, we see only the last group of
638- * tuples.This is clearly not the right way to do things
639- * !!
640- */
641-
642670nfields = PQnfields (results );
643671sqlca .sqlerrd [2 ]= ntuples = PQntuples (results );
644672status = true;
@@ -676,18 +704,67 @@ ECPGexecute(struct statement * stmt)
676704status = false;
677705break ;
678706}
679-
680- for (act_tuple = 0 ;act_tuple < ntuples ;act_tuple ++ )
707+
708+ /*
709+ * allocate memory for NULL pointers
710+ */
711+ if (var -> arrsize == 0 || var -> varcharsize == 0 )
712+ {
713+ switch (var -> type )
714+ {
715+ case ECPGt_char :
716+ case ECPGt_unsigned_char :
717+ if (var -> value == NULL )
718+ {
719+ var -> varcharsize = 0 ;
720+ /* check strlen for each tuple */
721+ for (act_tuple = 0 ;act_tuple < ntuples ;act_tuple ++ )
722+ {
723+ int len = strlen (PQgetvalue (results ,act_tuple ,act_field ));
724+
725+ if (len > var -> varcharsize )
726+ var -> varcharsize = len ;
727+ }
728+ var -> offset *=var -> varcharsize ;
729+ add_mem ((void * )(var -> value )= * ((void * * )(var -> pointer ))= (void * )ecpg_alloc (var -> offset * ntuples ,stmt -> lineno ),stmt -> lineno );
730+ }
731+ break ;
732+ #if 0
733+ case ECPGt_varchar :
734+ if (((struct ECPGgeneric_varchar * )var -> value )-> arr == NULL )
735+ {
736+ var -> varcharsize = 0 ;
737+ /* check strlen for each tuple */
738+ for (act_tuple = 0 ;act_tuple < ntuples ;act_tuple ++ )
739+ {
740+ int len = strlen (PQgetvalue (results ,act_tuple ,act_field ));
741+
742+ if (len > var -> varcharsize )
743+ var -> varcharsize = len ;
744+
745+ ((struct ECPGgeneric_varchar * ) ((long )var -> value + var -> offset * act_tuple ))-> arr = (char * )ecpg_alloc (len ,stmt -> lineno );
746+ }
747+ }
748+ break ;
749+ #endif
750+ default :
751+ if (var -> value == NULL )
752+ add_mem ((void * )(var -> value )= * ((void * * )(var -> pointer ))= (void * )ecpg_alloc (var -> offset * ntuples ,stmt -> lineno ),stmt -> lineno );
753+ break ;
754+ }
755+ }
756+
757+ for (act_tuple = 0 ;act_tuple < ntuples && status ;act_tuple ++ )
681758{
682759pval = PQgetvalue (results ,act_tuple ,act_field );
683760
684761ECPGlog ("ECPGexecute line %d: RESULT: %s\n" ,stmt -> lineno ,pval ?pval :"" );
685762
686- /* Now the pval is a pointer to thevar-> value. */
687- /* We will have to decode thevar-> value */
763+ /* Now the pval is a pointer to the value. */
764+ /* We will have to decode the value */
688765
689766/*
690- * check for nullvar-> value and set indicator
767+ * check for null value and set indicator
691768 * accordingly
692769 */
693770switch (var -> ind_type )
@@ -840,37 +917,28 @@ ECPGexecute(struct statement * stmt)
840917case ECPGt_char :
841918case ECPGt_unsigned_char :
842919{
843- if (var -> varcharsize == 0 )
920+ strncpy ((char * ) ((long )var -> value + var -> offset * act_tuple ),pval ,var -> varcharsize );
921+ if (var -> varcharsize && var -> varcharsize < strlen (pval ))
844922{
845- /* char* */
846- strncpy (((char * * )var -> value )[act_tuple ],pval ,strlen (pval ));
847- (((char * * )var -> value )[act_tuple ])[strlen (pval )]= '\0' ;
848- }
849- else
850- {
851- strncpy ((char * ) ((long )var -> value + var -> offset * act_tuple ),pval ,var -> varcharsize );
852- if (var -> varcharsize < strlen (pval ))
923+ /* truncation */
924+ switch (var -> ind_type )
853925{
854- /* truncation */
855- switch (var -> ind_type )
856- {
857- case ECPGt_short :
858- case ECPGt_unsigned_short :
859- ((short * )var -> ind_value )[act_tuple ]= var -> varcharsize ;
860- break ;
861- case ECPGt_int :
862- case ECPGt_unsigned_int :
863- ((int * )var -> ind_value )[act_tuple ]= var -> varcharsize ;
864- break ;
865- case ECPGt_long :
866- case ECPGt_unsigned_long :
867- ((long * )var -> ind_value )[act_tuple ]= var -> varcharsize ;
868- break ;
869- default :
870- break ;
871- }
872- sqlca .sqlwarn [0 ]= sqlca .sqlwarn [1 ]= 'W' ;
926+ case ECPGt_short :
927+ case ECPGt_unsigned_short :
928+ ((short * )var -> ind_value )[act_tuple ]= var -> varcharsize ;
929+ break ;
930+ case ECPGt_int :
931+ case ECPGt_unsigned_int :
932+ ((int * )var -> ind_value )[act_tuple ]= var -> varcharsize ;
933+ break ;
934+ case ECPGt_long :
935+ case ECPGt_unsigned_long :
936+ ((long * )var -> ind_value )[act_tuple ]= var -> varcharsize ;
937+ break ;
938+ default :
939+ break ;
873940}
941+ sqlca .sqlwarn [0 ]= sqlca .sqlwarn [1 ]= 'W' ;
874942}
875943}
876944break ;
@@ -914,8 +982,7 @@ ECPGexecute(struct statement * stmt)
914982break ;
915983
916984default :
917- register_error (ECPG_UNSUPPORTED ,"Unsupported type %s on line %d." ,
918- ECPGtype_name (var -> type ),stmt -> lineno );
985+ register_error (ECPG_UNSUPPORTED ,"Unsupported type %s on line %d." ,ECPGtype_name (var -> type ),stmt -> lineno );
919986status = false;
920987break ;
921988}