]> granicus.if.org Git - postgresql/blob - src/interfaces/ecpg/lib/ecpglib.c
From: Michael Meskes <Michael_Meskes@topmail.de>
[postgresql] / src / interfaces / ecpg / lib / ecpglib.c
1 /* Copyright comment */
2 /*
3  * The aim is to get a simpler inteface to the database routines.
4  * All the tidieous messing around with tuples is supposed to be hidden
5  * by this function.
6  */
7 /* Author: Linus Tolke
8    (actually most if the code is "borrowed" from the distribution and just
9    slightly modified)
10  */
11
12 /* Taken over as part of PostgreSQL by Michael Meskes <meskes@debian.org>
13    on Feb. 5th, 1998 */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <stdarg.h>
19 #include <string.h>
20 #include <ctype.h>
21
22 #include <libpq-fe.h>
23 #include <libpq/pqcomm.h>
24 #include <ecpgtype.h>
25 #include <ecpglib.h>
26 #include <sqlca.h>
27
28 /* variables visible to the programs */
29 int                     no_auto_trans;
30
31 static struct sqlca sqlca_init =
32 {
33         {'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '},
34         sizeof(struct sqlca),
35         0,
36         {0, {0}},
37         {'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '},
38         {0, 0, 0, 0, 0, 0},
39         {0, 0, 0, 0, 0, 0, 0, 0},
40         {0, 0, 0, 0, 0, 0, 0, 0}
41 };
42
43 struct sqlca sqlca =
44 {
45         {'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '},
46         sizeof(struct sqlca),
47         0,
48         {0, {0}},
49         {'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '},
50         {0, 0, 0, 0, 0, 0},
51         {0, 0, 0, 0, 0, 0, 0, 0},
52         {0, 0, 0, 0, 0, 0, 0, 0}
53 };
54
55 static struct connection
56 {
57         char    *name;
58         PGconn  *connection;
59         int     committed;
60         struct connection *next;
61 }               *all_connections = NULL, *actual_connection = NULL;
62
63 struct variable
64 {
65         enum ECPGttype type;
66         void       *value;
67         void       *pointer;
68         long            varcharsize;
69         long            arrsize;
70         long            offset;
71         enum ECPGttype ind_type;
72         void       *ind_value;
73         long            ind_varcharsize;
74         long            ind_arrsize;
75         long            ind_offset;
76         struct variable *next;
77 };
78
79 struct statement
80 {
81         int         lineno;
82         char       *command;
83         struct connection *connection;
84         struct variable *inlist;
85         struct variable *outlist;
86 };
87
88 struct prepared_statement
89 {
90         char                            *name;
91         struct statement                *stmt;
92         struct prepared_statement       *next;
93 }       *prep_stmts = NULL;
94
95 struct auto_mem
96 {
97         void *pointer;
98         struct auto_mem *next;
99 }       *auto_allocs = NULL;
100
101 static int      simple_debug = 0;
102 static FILE *debugstream = NULL;
103
104 static void
105 register_error(long code, char *fmt,...)
106 {
107         va_list         args;
108         struct auto_mem *am;
109         
110         sqlca.sqlcode = code;
111         va_start(args, fmt);
112         vsprintf(sqlca.sqlerrm.sqlerrmc, fmt, args);
113         va_end(args);
114         sqlca.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;
127 }
128
129 static struct connection *
130 get_connection(const char *connection_name)
131 {
132         struct connection *con = all_connections;;
133         
134         if (connection_name == NULL || strcmp(connection_name, "CURRENT") == 0)
135                 return actual_connection;
136                 
137         for (; con && strcmp(connection_name, con->name) != 0; con = con->next);
138         if (con)
139                 return con;
140         else
141                 return NULL;
142 }
143
144 static void
145 ECPGfinish(struct connection * act)
146 {
147         if (act != NULL)
148         {
149                 ECPGlog("ECPGfinish: finishing %s.\n", act->name);
150                 PQfinish(act->connection);
151                 /* remove act from the list */
152                 if (act == all_connections)
153                 {
154                         all_connections = act->next;
155                         free(act->name);
156                         free(act);
157                 }
158                 else
159                 {
160                         struct connection *con;
161
162                         for (con = all_connections; con->next && con->next != act; con = con->next);
163                         if (con->next)
164                         {
165                                 con->next = act->next;
166                                 free(act->name);
167                                 free(act);
168                         }
169                 }
170
171                 if (actual_connection == act)
172                         actual_connection = all_connections;
173         }
174         else
175                 ECPGlog("ECPGfinish: called an extra time.\n");
176 }
177
178 static char *
179 ecpg_alloc(long size, int lineno)
180 {
181         char       *new = (char *) malloc(size);
182
183         if (!new)
184         {
185                 ECPGlog("out of memory\n");
186                 register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
187                 return NULL;
188         }
189         
190         memset(new, '\0', size);
191         return (new);
192 }
193
194 static char *
195 ecpg_strdup(const char *string, int lineno)
196 {
197         char       *new = strdup(string);
198
199         if (!new)
200         {
201                 ECPGlog("out of memory\n");
202                 register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
203                 return NULL;
204         }
205
206         return (new);
207 }
208
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
218 /* This function returns a newly malloced string that has the ' and \
219    in the argument quoted with \.
220  */
221 static
222 char *
223 quote_postgres(char *arg, int lineno)
224 {
225         char       *res = (char *) ecpg_alloc(2 * strlen(arg) + 1, lineno);
226         int                     i,
227                                 ri;
228
229         if (!res)
230                 return (res);
231
232         for (i = 0, ri = 0; arg[i]; i++, ri++)
233         {
234                 switch (arg[i])
235                 {
236                         case '\'':
237                         case '\\':
238                                 res[ri++] = '\\';
239                         default:
240                                 ;
241                 }
242
243                 res[ri] = arg[i];
244         }
245         res[ri] = '\0';
246
247         return res;
248 }
249
250 /* This function returns a newly malloced string that has the \
251    in the strings inside the argument quoted with another \.
252  */
253 static
254 char *
255 quote_strings(char *arg, int lineno)
256 {
257         char       *res = (char *) ecpg_alloc(2 * strlen(arg) + 1, lineno);
258         int                     i,
259                                 ri;
260         bool                    string = false;
261
262         if (!res)
263                 return (res);
264
265         for (i = 0, ri = 0; arg[i]; i++, ri++)
266         {
267                 switch (arg[i])
268                 {
269                         case '\'':
270                                 string = string ? false : true;
271                                 break;
272                         case '\\':
273                                 res[ri++] = '\\';
274                         default:
275                                 ;
276                 }
277
278                 res[ri] = arg[i];
279         }
280         res[ri] = '\0';
281
282         return res;
283 }
284
285 /*
286  * create a list of variables 
287  * The variables are listed with input variables preceeding outputvariables
288  * The end of each group is marked by an end marker.
289  * per variable we list:
290  * type - as defined in ecpgtype.h
291  * value - where to store the data
292  * varcharsize - length of string in case we have a stringvariable, else 0
293  * arraysize - 0 for pointer (we don't know the size of the array),
294  * 1 for simple variable, size for arrays
295  * offset - offset between ith and (i+1)th entry in an array,
296  * normally that means sizeof(type)
297  * ind_type - type of indicator variable
298  * ind_value - pointer to indicator variable
299  * ind_varcharsize - empty
300  * ind_arraysize -  arraysize of indicator array
301  * ind_offset - indicator offset
302  */
303 static bool
304 create_statement(int lineno, struct connection *connection, struct statement ** stmt, char *query, va_list ap)
305 {
306         struct variable **list = &((*stmt)->inlist);
307         enum ECPGttype type;
308
309         if (!(*stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno)))
310                 return false;
311
312         (*stmt)->command = query;
313         (*stmt)->connection = connection;
314         (*stmt)->lineno = lineno;
315
316         list = &((*stmt)->inlist);
317
318         type = va_arg(ap, enum ECPGttype);
319
320         while (type != ECPGt_EORT)
321         {
322                 if (type == ECPGt_EOIT)
323                         list = &((*stmt)->outlist);
324                 else
325                 {
326                         struct variable *var,
327                                            *ptr;
328
329                         if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
330                                 return false;
331
332                         var->type = type;
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                         
344                         var->varcharsize = va_arg(ap, long);
345                         var->arrsize = va_arg(ap, long);
346                         var->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                         
353                         var->ind_type = va_arg(ap, enum ECPGttype);
354                         var->ind_value = va_arg(ap, void *);
355                         var->ind_varcharsize = va_arg(ap, long);
356                         var->ind_arrsize = va_arg(ap, long);
357                         var->ind_offset = va_arg(ap, long);
358                         var->next = NULL;
359
360                         for (ptr = *list; ptr && ptr->next; ptr = ptr->next);
361
362                         if (ptr == NULL)
363                                 *list = var;
364                         else
365                                 ptr->next = var;
366                 }
367
368                 type = va_arg(ap, enum ECPGttype);
369         }
370
371         return (true);
372 }
373
374 static char *
375 next_insert(char *text)
376 {
377         char *ptr = text;
378         bool string = false;
379         
380         for (; ptr[1] != '\0' && (ptr[0] != ';' || ptr[1] != ';' || string); ptr++)
381                 if (ptr[0] == '\'')
382                         string = string ? false : true;
383                         
384         return (ptr[1] == '\0') ? NULL : ptr;
385 }
386
387 static bool
388 ECPGexecute(struct statement * stmt)
389 {
390         bool            status = false;
391         char       *copiedquery;
392         PGresult   *results;
393         PGnotify   *notify;
394         struct variable *var;
395
396         memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
397
398         copiedquery = ecpg_strdup(stmt->command, stmt->lineno);
399
400         /*
401          * Now, if the type is one of the fill in types then we take the
402          * argument and enter that in the string at the first %s position.
403          * Then if there are any more fill in types we fill in at the next and
404          * so on.
405          */
406         var = stmt->inlist;
407         while (var)
408         {
409                 char       *newcopy;
410                 char       *mallocedval = NULL;
411                 char       *tobeinserted = NULL;
412                 char       *p;
413                 char            buff[20];
414
415                 /*
416                  * Some special treatment is needed for records since we want
417                  * their contents to arrive in a comma-separated list on insert (I
418                  * think).
419                  */
420
421                 buff[0] = '\0';
422
423                 /* check for null value and set input buffer accordingly */
424                 switch (var->ind_type)
425                 {
426                         case ECPGt_short:
427                         case ECPGt_unsigned_short:
428                                 if (*(short *) var->ind_value < 0)
429                                         strcpy(buff, "null");
430                                 break;
431                         case ECPGt_int:
432                         case ECPGt_unsigned_int:
433                                 if (*(int *) var->ind_value < 0)
434                                         strcpy(buff, "null");
435                                 break;
436                         case ECPGt_long:
437                         case ECPGt_unsigned_long:
438                                 if (*(long *) var->ind_value < 0L)
439                                         strcpy(buff, "null");
440                                 break;
441                         default:
442                                 break;
443                 }
444
445                 if (*buff == '\0')
446                 {
447                         switch (var->type)
448                         {
449                                 case ECPGt_short:
450                                 case ECPGt_int:
451                                         sprintf(buff, "%d", *(int *) var->value);
452                                         tobeinserted = buff;
453                                         break;
454
455                                 case ECPGt_unsigned_short:
456                                 case ECPGt_unsigned_int:
457                                         sprintf(buff, "%d", *(unsigned int *) var->value);
458                                         tobeinserted = buff;
459                                         break;
460
461                                 case ECPGt_long:
462                                         sprintf(buff, "%ld", *(long *) var->value);
463                                         tobeinserted = buff;
464                                         break;
465
466                                 case ECPGt_unsigned_long:
467                                         sprintf(buff, "%ld", *(unsigned long *) var->value);
468                                         tobeinserted = buff;
469                                         break;
470
471                                 case ECPGt_float:
472                                         sprintf(buff, "%.14g", *(float *) var->value);
473                                         tobeinserted = buff;
474                                         break;
475
476                                 case ECPGt_double:
477                                         sprintf(buff, "%.14g", *(double *) var->value);
478                                         tobeinserted = buff;
479                                         break;
480
481                                 case ECPGt_bool:
482                                         sprintf(buff, "'%c'", (*(char *) var->value ? 't' : 'f'));
483                                         tobeinserted = buff;
484                                         break;
485
486                                 case ECPGt_char:
487                                 case ECPGt_unsigned_char:
488                                         {
489                                                 /* set slen to string length if type is char * */
490                                                 int                     slen = (var->varcharsize == 0) ? strlen((char *) var->value) : var->varcharsize;
491                                                 char       *tmp;
492
493                                                 if (!(newcopy = ecpg_alloc(slen + 1, stmt->lineno)))
494                                                         return false;
495
496                                                 strncpy(newcopy, (char *) var->value, slen);
497                                                 newcopy[slen] = '\0';
498
499                                                 if (!(mallocedval = (char *) ecpg_alloc(2 * strlen(newcopy) + 3, stmt->lineno)))
500                                                         return false;
501
502                                                 strcpy(mallocedval, "'");
503                                                 tmp = quote_postgres(newcopy, stmt->lineno);
504                                                 if (!tmp)
505                                                         return false;
506
507                                                 strcat(mallocedval, tmp);
508                                                 strcat(mallocedval, "'");
509
510                                                 free(newcopy);
511
512                                                 tobeinserted = mallocedval;
513                                         }
514                                         break;
515                                 case ECPGt_char_variable:
516                                         {
517                                                 int                     slen = strlen((char *) var->value);
518                                                 char       *tmp;
519
520                                                 if (!(newcopy = ecpg_alloc(slen + 1, stmt->lineno)))
521                                                         return false;
522
523                                                 strncpy(newcopy, (char *) var->value, slen);
524                                                 newcopy[slen] = '\0';
525                                                 if (!(mallocedval = (char *) ecpg_alloc(2 * strlen(newcopy) + 1, stmt->lineno)))
526                                                         return false;
527
528                                                 tmp = quote_strings(newcopy, stmt->lineno);
529                                                 if (!tmp)
530                                                         return false;
531
532                                                 strcat(mallocedval, tmp);
533                                                 free(newcopy);
534
535                                                 tobeinserted = mallocedval;
536                                         }
537                                         break;
538                                 case ECPGt_varchar:
539                                         {
540                                                 struct ECPGgeneric_varchar *variable =
541                                                 (struct ECPGgeneric_varchar *) (var->value);
542                                                 char       *tmp;
543
544                                                 if (!(newcopy = (char *) ecpg_alloc(variable->len + 1, stmt->lineno)))
545                                                         return false;
546
547                                                 strncpy(newcopy, variable->arr, variable->len);
548                                                 newcopy[variable->len] = '\0';
549
550                                                 if (!(mallocedval = (char *) ecpg_alloc(2 * strlen(newcopy) + 3, stmt->lineno)))
551                                                         return false;
552
553                                                 strcpy(mallocedval, "'");
554                                                 tmp = quote_postgres(newcopy, stmt->lineno);
555                                                 if (!tmp)
556                                                         return false;
557
558                                                 strcat(mallocedval, tmp);
559                                                 strcat(mallocedval, "'");
560
561                                                 free(newcopy);
562
563                                                 tobeinserted = mallocedval;
564                                         }
565                                         break;
566
567                                 default:
568                                         /* Not implemented yet */
569                                         register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
570                                                                  ECPGtype_name(var->type), stmt->lineno);
571                                         return false;
572                                         break;
573                         }
574                 }
575                 else
576                         tobeinserted = buff;
577
578                 /*
579                  * Now tobeinserted points to an area that is to be inserted at
580                  * the first %s
581                  */
582                 if (!(newcopy = (char *) ecpg_alloc(strlen(copiedquery) + strlen(tobeinserted) + 1, stmt->lineno)))
583                         return false;
584
585                 strcpy(newcopy, copiedquery);
586                 if ((p = next_insert(newcopy)) == NULL)
587                 {
588
589                         /*
590                          * We have an argument but we dont have the matched up string
591                          * in the string
592                          */
593                         register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", stmt->lineno);
594                         return false;
595                 }
596                 else
597                 {
598                         strcpy(p, tobeinserted);
599
600                         /*
601                          * The strange thing in the second argument is the rest of the
602                          * string from the old string
603                          */
604                         strcat(newcopy,
605                                    copiedquery
606                                    + (p - newcopy)
607                                    + sizeof(";;") - 1 /* don't count the '\0' */);
608                 }
609
610                 /*
611                  * Now everything is safely copied to the newcopy. Lets free the
612                  * oldcopy and let the copiedquery get the var->value from the
613                  * newcopy.
614                  */
615                 if (mallocedval != NULL)
616                 {
617                         free(mallocedval);
618                         mallocedval = NULL;
619                 }
620
621                 free(copiedquery);
622                 copiedquery = newcopy;
623
624                 var = var->next;
625         }
626
627         /* Check if there are unmatched things left. */
628         if (next_insert(copiedquery) != NULL)
629         {
630                 register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
631                 return false;
632         }
633
634         /* Now the request is built. */
635
636         if (stmt->connection->committed && !no_auto_trans)
637         {
638                 if ((results = PQexec(stmt->connection->connection, "begin transaction")) == NULL)
639                 {
640                         register_error(ECPG_TRANS, "Error starting transaction line %d.", stmt->lineno);
641                         return false;
642                 }
643                 PQclear(results);
644                 stmt->connection->committed = false;
645         }
646
647         ECPGlog("ECPGexecute line %d: QUERY: %s on connection %s\n", stmt->lineno, copiedquery, stmt->connection->name);
648         results = PQexec(stmt->connection->connection, copiedquery);
649         free(copiedquery);
650
651         if (results == NULL)
652         {
653                 ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
654                                 PQerrorMessage(stmt->connection->connection));
655                 register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
656                         PQerrorMessage(stmt->connection->connection), stmt->lineno);
657         }
658         else
659         {
660                 sqlca.sqlerrd[2] = 0;
661                 var = stmt->outlist;
662                 switch (PQresultStatus(results))
663                 {
664                                 int                     nfields,
665                                                         ntuples,
666                                                         act_tuple,
667                                                         act_field;
668
669                         case PGRES_TUPLES_OK:
670                                 nfields = PQnfields(results);
671                                 sqlca.sqlerrd[2] = ntuples = PQntuples(results);
672                                 status = true;
673
674                                 if (ntuples < 1)
675                                 {
676                                         ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d\n",
677                                                         stmt->lineno, ntuples);
678                                         register_error(ECPG_NOT_FOUND, "Data not found line %d.", stmt->lineno);
679                                         status = false;
680                                         break;
681                                 }
682
683                                 for (act_field = 0; act_field < nfields && status; act_field++)
684                                 {
685                                         char       *pval;
686                                         char       *scan_length;
687
688                                         if (var == NULL)
689                                         {
690                                                 ECPGlog("ECPGexecute line %d: Too few arguments.\n", stmt->lineno);
691                                                 register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
692                                                 return (false);
693                                         }
694
695                                         /*
696                                          * if we don't have enough space, we cannot read all
697                                          * tuples
698                                          */
699                                         if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
700                                         {
701                                                 ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d don't fit into array of %d\n",
702                                                                 stmt->lineno, ntuples, var->arrsize);
703                                                 register_error(ECPG_TOO_MANY_MATCHES, "Too many matches line %d.", stmt->lineno);
704                                                 status = false;
705                                                 break;
706                                         }
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++)
758                                         {
759                                                 pval = PQgetvalue(results, act_tuple, act_field);
760
761                                                 ECPGlog("ECPGexecute line %d: RESULT: %s\n", stmt->lineno, pval ? pval : "");
762
763                                                 /* Now the pval is a pointer to the value. */
764                                                 /* We will have to decode the value */
765
766                                                 /*
767                                                  * check for null value and set indicator
768                                                  * accordingly
769                                                  */
770                                                 switch (var->ind_type)
771                                                 {
772                                                         case ECPGt_short:
773                                                         case ECPGt_unsigned_short:
774                                                                 ((short *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
775                                                                 break;
776                                                         case ECPGt_int:
777                                                         case ECPGt_unsigned_int:
778                                                                 ((int *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
779                                                                 break;
780                                                         case ECPGt_long:
781                                                         case ECPGt_unsigned_long:
782                                                                 ((long *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
783                                                                 break;
784                                                         default:
785                                                                 break;
786                                                 }
787
788                                                 switch (var->type)
789                                                 {
790                                                                 long            res;
791                                                                 unsigned long ures;
792                                                                 double          dres;
793
794                                                         case ECPGt_short:
795                                                         case ECPGt_int:
796                                                         case ECPGt_long:
797                                                                 if (pval)
798                                                                 {
799                                                                         res = strtol(pval, &scan_length, 10);
800                                                                         if (*scan_length != '\0')       /* Garbage left */
801                                                                         {
802                                                                                 register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.",
803                                                                                                          pval, stmt->lineno);
804                                                                                 status = false;
805                                                                                 res = 0L;
806                                                                         }
807                                                                 }
808                                                                 else
809                                                                         res = 0L;
810
811                                                                 /* Again?! Yes */
812                                                                 switch (var->type)
813                                                                 {
814                                                                         case ECPGt_short:
815                                                                                 ((short *) var->value)[act_tuple] = (short) res;
816                                                                                 break;
817                                                                         case ECPGt_int:
818                                                                                 ((int *) var->value)[act_tuple] = (int) res;
819                                                                                 break;
820                                                                         case ECPGt_long:
821                                                                                 ((long *) var->value)[act_tuple] = res;
822                                                                                 break;
823                                                                         default:
824                                                                                 /* Cannot happen */
825                                                                                 break;
826                                                                 }
827                                                                 break;
828
829                                                         case ECPGt_unsigned_short:
830                                                         case ECPGt_unsigned_int:
831                                                         case ECPGt_unsigned_long:
832                                                                 if (pval)
833                                                                 {
834                                                                         ures = strtoul(pval, &scan_length, 10);
835                                                                         if (*scan_length != '\0')       /* Garbage left */
836                                                                         {
837                                                                                 register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.",
838                                                                                                          pval, stmt->lineno);
839                                                                                 status = false;
840                                                                                 ures = 0L;
841                                                                         }
842                                                                 }
843                                                                 else
844                                                                         ures = 0L;
845
846                                                                 /* Again?! Yes */
847                                                                 switch (var->type)
848                                                                 {
849                                                                         case ECPGt_unsigned_short:
850                                                                                 ((unsigned short *) var->value)[act_tuple] = (unsigned short) ures;
851                                                                                 break;
852                                                                         case ECPGt_unsigned_int:
853                                                                                 ((unsigned int *) var->value)[act_tuple] = (unsigned int) ures;
854                                                                                 break;
855                                                                         case ECPGt_unsigned_long:
856                                                                                 ((unsigned long *) var->value)[act_tuple] = ures;
857                                                                                 break;
858                                                                         default:
859                                                                                 /* Cannot happen */
860                                                                                 break;
861                                                                 }
862                                                                 break;
863
864
865                                                         case ECPGt_float:
866                                                         case ECPGt_double:
867                                                                 if (pval)
868                                                                 {
869                                                                         dres = strtod(pval, &scan_length);
870                                                                         if (*scan_length != '\0')       /* Garbage left */
871                                                                         {
872                                                                                 register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.",
873                                                                                                          pval, stmt->lineno);
874                                                                                 status = false;
875                                                                                 dres = 0.0;
876                                                                         }
877                                                                 }
878                                                                 else
879                                                                         dres = 0.0;
880
881                                                                 /* Again?! Yes */
882                                                                 switch (var->type)
883                                                                 {
884                                                                         case ECPGt_float:
885                                                                                 ((float *) var->value)[act_tuple] = dres;
886                                                                                 break;
887                                                                         case ECPGt_double:
888                                                                                 ((double *) var->value)[act_tuple] = dres;
889                                                                                 break;
890                                                                         default:
891                                                                                 /* Cannot happen */
892                                                                                 break;
893                                                                 }
894                                                                 break;
895
896                                                         case ECPGt_bool:
897                                                                 if (pval)
898                                                                 {
899                                                                         if (pval[0] == 'f' && pval[1] == '\0')
900                                                                         {
901                                                                                 ((char *) var->value)[act_tuple] = false;
902                                                                                 break;
903                                                                         }
904                                                                         else if (pval[0] == 't' && pval[1] == '\0')
905                                                                         {
906                                                                                 ((char *) var->value)[act_tuple] = true;
907                                                                                 break;
908                                                                         }
909                                                                 }
910
911                                                                 register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
912                                                                                            (pval ? pval : "NULL"),
913                                                                                            stmt->lineno);
914                                                                 status = false;
915                                                                 break;
916
917                                                         case ECPGt_char:
918                                                         case ECPGt_unsigned_char:
919                                                                 {
920                                                                         strncpy((char *) ((long) var->value + var->offset * act_tuple), pval, var->varcharsize);
921                                                                         if (var->varcharsize && var->varcharsize < strlen(pval))
922                                                                         {
923                                                                                 /* truncation */
924                                                                                 switch (var->ind_type)
925                                                                                 {
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;
940                                                                                 }
941                                                                                 sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
942                                                                         }
943                                                                 }
944                                                                 break;
945
946                                                         case ECPGt_varchar:
947                                                                 {
948                                                                         struct ECPGgeneric_varchar *variable =
949                                                                         (struct ECPGgeneric_varchar *) ((long) var->value + var->offset * act_tuple);
950
951                                                                         if (var->varcharsize == 0)
952                                                                                 strncpy(variable->arr, pval, strlen(pval));
953                                                                         else
954                                                                                 strncpy(variable->arr, pval, var->varcharsize);
955
956                                                                         variable->len = strlen(pval);
957                                                                         if (var->varcharsize > 0 && variable->len > var->varcharsize)
958                                                                         {
959                                                                                 /* truncation */
960                                                                                 switch (var->ind_type)
961                                                                                 {
962                                                                                         case ECPGt_short:
963                                                                                         case ECPGt_unsigned_short:
964                                                                                                 ((short *) var->ind_value)[act_tuple] = var->varcharsize;
965                                                                                                 break;
966                                                                                         case ECPGt_int:
967                                                                                         case ECPGt_unsigned_int:
968                                                                                                 ((int *) var->ind_value)[act_tuple] = var->varcharsize;
969                                                                                                 break;
970                                                                                         case ECPGt_long:
971                                                                                         case ECPGt_unsigned_long:
972                                                                                                 ((long *) var->ind_value)[act_tuple] = var->varcharsize;
973                                                                                                 break;
974                                                                                         default:
975                                                                                                 break;
976                                                                                 }
977                                                                                 sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
978
979                                                                                 variable->len = var->varcharsize;
980                                                                         }
981                                                                 }
982                                                                 break;
983
984                                                         default:
985                                                                 register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.", ECPGtype_name(var->type), stmt->lineno);
986                                                                 status = false;
987                                                                 break;
988                                                 }
989                                         }
990                                         var = var->next;
991                                 }
992
993                                 if (status && var != NULL)
994                                 {
995                                         register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", stmt->lineno);
996                                         status = false;
997                                 }
998
999                                 PQclear(results);
1000                                 break;
1001                         case PGRES_EMPTY_QUERY:
1002                                 /* do nothing */
1003                                 register_error(ECPG_EMPTY, "Empty query line %d.", stmt->lineno);
1004                                 break;
1005                         case PGRES_COMMAND_OK:
1006                                 status = true;
1007                                 sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
1008                                 ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, PQcmdStatus(results));
1009                                 break;
1010                         case PGRES_NONFATAL_ERROR:
1011                         case PGRES_FATAL_ERROR:
1012                         case PGRES_BAD_RESPONSE:
1013                                 ECPGlog("ECPGexecute line %d: Error: %s",
1014                                                 stmt->lineno, PQerrorMessage(stmt->connection->connection));
1015                                 register_error(ECPG_PGSQL, "Error: %s line %d.",
1016                                                            PQerrorMessage(stmt->connection->connection), stmt->lineno);
1017                                 status = false;
1018                                 break;
1019                         case PGRES_COPY_OUT:
1020                                 ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", stmt->lineno);
1021                                 PQendcopy(stmt->connection->connection);
1022                                 break;
1023                         case PGRES_COPY_IN:
1024                                 ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", stmt->lineno);
1025                                 PQendcopy(stmt->connection->connection);
1026                                 break;
1027                         default:
1028                                 ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
1029                                                 stmt->lineno);
1030                                 register_error(ECPG_PGSQL, "Postgres error line %d.", stmt->lineno);
1031                                 status = false;
1032                                 break;
1033                 }
1034         }
1035
1036         /* check for asynchronous returns */
1037         notify = PQnotifies(stmt->connection->connection);
1038         if (notify)
1039         {
1040                 ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
1041                                 stmt->lineno, notify->relname, notify->be_pid);
1042                 free(notify);
1043         }
1044
1045         return status;
1046 }
1047
1048 bool
1049 ECPGdo(int lineno, const char *connection_name, char *query,...)
1050 {
1051         va_list         args;
1052         struct statement *stmt;
1053         struct connection *con = get_connection(connection_name);
1054
1055         if (con == NULL)
1056         {
1057                 register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name, lineno);
1058                 return (false);
1059         }
1060                 
1061         va_start(args, query);
1062         if (create_statement(lineno, con, &stmt, query, args) == false)
1063                 return (false);
1064         va_end(args);
1065
1066         /* are we connected? */
1067         if (con == NULL || con->connection == NULL)
1068         {
1069                 ECPGlog("ECPGdo: not connected to %s\n", con->name);
1070                 register_error(ECPG_NOT_CONN, "Not connected in line %d", lineno);
1071                 return false;
1072         }
1073
1074         return (ECPGexecute(stmt));
1075 }
1076
1077
1078 bool
1079 ECPGtrans(int lineno, const char *connection_name, const char *transaction)
1080 {
1081         PGresult   *res;
1082         struct connection *con = get_connection(connection_name);
1083         
1084         if (con == NULL)
1085         {
1086                 register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name, lineno);
1087                 return (false);
1088         }
1089
1090         ECPGlog("ECPGtrans line %d action = %s connection = %s\n", lineno, transaction, con->name);
1091
1092         /* if we have no connection we just simulate the command */
1093         if (con && con->connection)
1094         {
1095                 if ((res = PQexec(con->connection, transaction)) == NULL)
1096                 {
1097                         register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
1098                         return FALSE;
1099                 }
1100                 PQclear(res);
1101         }
1102         if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0)
1103         {
1104                 struct prepared_statement *this;
1105                         
1106                 con->committed = true;
1107
1108                 /* deallocate all prepared statements */
1109                 for (this = prep_stmts; this != NULL; this = this->next)
1110                 {
1111                         bool b = ECPGdeallocate(lineno, this->name);
1112                 
1113                         if (!b) 
1114                                 return false;
1115                 }
1116         }
1117
1118         return true;
1119 }
1120
1121 bool
1122 ECPGsetconn(int lineno, const char *connection_name)
1123 {
1124         struct connection *con = get_connection(connection_name);
1125
1126         if (con)
1127         {
1128                 actual_connection = con;
1129                 return true;
1130         }
1131         else
1132         {
1133                 register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name, lineno);
1134                 return false;
1135         }
1136 }
1137
1138 bool
1139 ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd, const char *connection_name)
1140 {
1141         struct connection *this = (struct connection *) ecpg_alloc(sizeof(struct connection), lineno);
1142
1143         if (!this)
1144                 return false;
1145
1146         if (dbname == NULL && connection_name == NULL)
1147                 connection_name = "DEFAULT";
1148
1149         /* add connection to our list */
1150         if (connection_name != NULL)
1151                 this->name = ecpg_strdup(connection_name, lineno);
1152         else
1153                 this->name = ecpg_strdup(dbname, lineno);
1154
1155         if (all_connections == NULL)
1156                 this->next = NULL;
1157         else
1158                 this->next = all_connections;
1159
1160         actual_connection = all_connections = this;
1161
1162         ECPGlog("ECPGconnect: opening database %s %s%s\n", dbname ? dbname : "NULL", user ? "for user " : "", user ? user : "");
1163
1164         sqlca.sqlcode = 0;
1165
1166         this->connection = PQsetdbLogin(NULL, NULL, NULL, NULL, dbname, user, passwd);
1167
1168         if (PQstatus(this->connection) == CONNECTION_BAD)
1169         {
1170                 ECPGfinish(this);
1171                 ECPGlog("connect: could not open database %s %s%s in line %d\n", dbname ? dbname : "NULL", user ? "for user " : "", user ? user : "", lineno);
1172                 register_error(ECPG_CONNECT, "connect: could not open database %s.", dbname ? dbname : "NULL");
1173                 return false;
1174         }
1175         
1176         this->committed = true;
1177
1178         return true;
1179 }
1180
1181 bool
1182 ECPGdisconnect(int lineno, const char *connection_name)
1183 {
1184         struct connection *con;
1185
1186         if (strcmp(connection_name, "ALL") == 0)
1187         {
1188                 for (con = all_connections; con;)
1189                 {
1190                         struct connection *f = con;
1191
1192                         con = con->next;
1193                         ECPGfinish(f);
1194                 }
1195         }
1196         else
1197         {
1198                 con = get_connection(connection_name);
1199                 
1200                 if (con == NULL)
1201                 {
1202                         ECPGlog("disconnect: not connected to connection %s\n", connection_name);
1203                         register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name, lineno);
1204                         return false;
1205                 }
1206                 else
1207                         ECPGfinish(con);
1208         }
1209
1210         return true;
1211 }
1212
1213 void
1214 ECPGdebug(int n, FILE *dbgs)
1215 {
1216         simple_debug = n;
1217         debugstream = dbgs;
1218         ECPGlog("ECPGdebug: set to %d\n", simple_debug);
1219 }
1220
1221 void
1222 ECPGlog(const char *format,...)
1223 {
1224         va_list         ap;
1225
1226         if (simple_debug)
1227         {
1228                 char       *f = (char *) malloc(strlen(format) + 100);
1229
1230                 if (!f)
1231                         return;
1232
1233                 sprintf(f, "[%d]: %s", (int) getpid(), format);
1234
1235                 va_start(ap, format);
1236                 vfprintf(debugstream, f, ap);
1237                 va_end(ap);
1238
1239                 free(f);
1240         }
1241 }
1242
1243 /* print out an error message */
1244 void
1245 sqlprint(void)
1246 {
1247         sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
1248         printf("sql error %s\n", sqlca.sqlerrm.sqlerrmc);
1249 }
1250
1251 static bool
1252 isvarchar(unsigned char c)
1253 {
1254         if (isalnum(c))
1255                 return true;
1256         
1257         if (c == '_' || c == '>' || c == '-' || c == '.')
1258                 return true;
1259                 
1260         if (c >= 128)
1261                 return true;
1262                 
1263         return(false);
1264 }
1265
1266 static void
1267 replace_variables(char *text)
1268 {
1269         char *ptr = text;
1270         bool string = false;
1271         
1272         for (; *ptr != '\0'; ptr++)
1273         {
1274                 if (*ptr == '\'')
1275                         string = string ? false : true;
1276                         
1277                 if (!string && *ptr == ':')
1278                 {
1279                         ptr[0] = ptr[1] = ';';
1280                         for (ptr += 2; *ptr && isvarchar(*ptr); ptr++)
1281                                 *ptr = ' ';
1282                 }
1283         }
1284 }
1285
1286 /* handle the EXEC SQL PREPARE statement */
1287 bool
1288 ECPGprepare(int lineno, char *name, char *variable)
1289 {
1290         struct statement *stmt;
1291         struct prepared_statement *this;
1292         
1293         /* check if we already have prepared this statement */
1294         for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);              
1295         if (this)
1296         {
1297                 bool b = ECPGdeallocate(lineno, name);
1298                 
1299                 if (!b) 
1300                         return false;
1301         }
1302         
1303         this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno);
1304         if (!this)
1305                 return false;
1306                 
1307         stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
1308         if (!stmt)
1309         {
1310                 free(this);
1311                 return false;
1312         }
1313
1314         /* create statement */
1315         stmt->lineno = lineno;
1316         stmt->connection = NULL;
1317         stmt->command = ecpg_strdup(variable, lineno);
1318         stmt->inlist = stmt->outlist = NULL;
1319         
1320         /* if we have C variables in our statment replace them with ';;' */
1321         replace_variables(stmt->command);                       
1322         
1323         /* add prepared statement to our list */
1324         this->name = ecpg_strdup(name, lineno);
1325         this->stmt = stmt;
1326
1327         if (prep_stmts == NULL)
1328                 this->next = NULL;
1329         else
1330                 this->next = prep_stmts;
1331
1332         prep_stmts = this;
1333         return true;
1334 }
1335
1336 /* handle the EXEC SQL DEALLOCATE PREPARE statement */
1337 bool
1338 ECPGdeallocate(int lineno, char *name)
1339 {
1340         struct prepared_statement *this, *prev;
1341
1342         /* check if we really have prepared this statement */
1343         for (this = prep_stmts, prev = NULL; this != NULL && strcmp(this->name, name) != 0; prev = this, this = this->next);            
1344         if (this)
1345         {
1346                 /* okay, free all the resources */
1347                 free(this->name);
1348                 free(this->stmt->command);
1349                 free(this->stmt);
1350                 if (prev != NULL)
1351                         prev->next = this->next;
1352                 else
1353                         prep_stmts = this->next;
1354                 
1355                 return true;
1356         }
1357         ECPGlog("deallocate_prepare: invalid statement name %s\n", name);
1358         register_error(ECPG_INVALID_STMT, "Invalid statement name %s in line %d", name, lineno);
1359         return false;
1360 }
1361
1362 /* return the prepared statement */
1363 char *
1364 ECPGprepared_statement(char *name)
1365 {
1366         struct prepared_statement *this;
1367         
1368         for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
1369         return (this) ? this->stmt->command : NULL;
1370 }
1371