~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/interfaces/ecpg/ecpglib/execute.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.38.4.1 2005-03-18 10:01:14 meskes Exp $ */
 
2
 
 
3
/*
 
4
 * The aim is to get a simpler inteface to the database routines.
 
5
 * All the tidieous messing around with tuples is supposed to be hidden
 
6
 * by this function.
 
7
 */
 
8
/* Author: Linus Tolke
 
9
   (actually most if the code is "borrowed" from the distribution and just
 
10
   slightly modified)
 
11
 */
 
12
 
 
13
/* Taken over as part of PostgreSQL by Michael Meskes <meskes@postgresql.org>
 
14
   on Feb. 5th, 1998 */
 
15
 
 
16
#define POSTGRES_ECPG_INTERNAL
 
17
#include "postgres_fe.h"
 
18
 
 
19
#include <stdio.h>
 
20
#include <locale.h>
 
21
 
 
22
#include "pg_type.h"
 
23
 
 
24
#include "ecpgtype.h"
 
25
#include "ecpglib.h"
 
26
#include "ecpgerrno.h"
 
27
#include "extern.h"
 
28
#include "sqlca.h"
 
29
#include "sql3types.h"
 
30
#include "pgtypes_numeric.h"
 
31
#include "pgtypes_date.h"
 
32
#include "pgtypes_timestamp.h"
 
33
#include "pgtypes_interval.h"
 
34
 
 
35
/* This function returns a newly malloced string that has the  \
 
36
   in the argument quoted with \ and the ' quoted with ' as SQL92 says.
 
37
 */
 
38
static char *
 
39
quote_postgres(char *arg, int lineno)
 
40
{
 
41
        char       *res = (char *) ECPGalloc(2 * strlen(arg) + 3, lineno);
 
42
        int                     i,
 
43
                                ri = 0;
 
44
 
 
45
        if (!res)
 
46
                return (res);
 
47
 
 
48
        res[ri++] = '\'';
 
49
 
 
50
        for (i = 0; arg[i]; i++, ri++)
 
51
        {
 
52
                switch (arg[i])
 
53
                {
 
54
                        case '\'':
 
55
                                res[ri++] = '\'';
 
56
                                break;
 
57
                        case '\\':
 
58
                                res[ri++] = '\\';
 
59
                                break;
 
60
                        default:
 
61
                                ;
 
62
                }
 
63
                res[ri] = arg[i];
 
64
        }
 
65
 
 
66
        res[ri++] = '\'';
 
67
        res[ri] = '\0';
 
68
 
 
69
        return res;
 
70
}
 
71
 
 
72
#if defined(__GNUC__) && (defined (__powerpc__) || defined(__AMD64__))
 
73
#define APREF ap
 
74
#else
 
75
#define APREF *ap
 
76
#endif
 
77
 
 
78
void
 
79
ECPGget_variable(va_list APREF, enum ECPGttype type, struct variable * var, bool indicator)
 
80
{
 
81
        var->type = type;
 
82
        var->pointer = va_arg(APREF, char *);
 
83
 
 
84
        var->varcharsize = va_arg(APREF, long);
 
85
        var->arrsize = va_arg(APREF, long);
 
86
        var->offset = va_arg(APREF, long);
 
87
 
 
88
        if (var->arrsize == 0 || var->varcharsize == 0)
 
89
                var->value = *((char **) (var->pointer));
 
90
        else
 
91
                var->value = var->pointer;
 
92
 
 
93
        /*
 
94
         * negative values are used to indicate an array without given bounds
 
95
         */
 
96
        /* reset to zero for us */
 
97
        if (var->arrsize < 0)
 
98
                var->arrsize = 0;
 
99
        if (var->varcharsize < 0)
 
100
                var->varcharsize = 0;
 
101
 
 
102
        var->next = NULL;
 
103
 
 
104
        if (indicator)
 
105
        {
 
106
                var->ind_type = va_arg(APREF, enum ECPGttype);
 
107
                var->ind_pointer = va_arg(APREF, char *);
 
108
                var->ind_varcharsize = va_arg(APREF, long);
 
109
                var->ind_arrsize = va_arg(APREF, long);
 
110
                var->ind_offset = va_arg(APREF, long);
 
111
 
 
112
                if (var->ind_type != ECPGt_NO_INDICATOR
 
113
                        && (var->ind_arrsize == 0 || var->ind_varcharsize == 0))
 
114
                        var->ind_value = *((char **) (var->ind_pointer));
 
115
                else
 
116
                        var->ind_value = var->ind_pointer;
 
117
 
 
118
                /*
 
119
                 * negative values are used to indicate an array without given
 
120
                 * bounds
 
121
                 */
 
122
                /* reset to zero for us */
 
123
                if (var->ind_arrsize < 0)
 
124
                        var->ind_arrsize = 0;
 
125
                if (var->ind_varcharsize < 0)
 
126
                        var->ind_varcharsize = 0;
 
127
        }
 
128
}
 
129
#undef APREF
 
130
 
 
131
/*
 
132
 * create a list of variables
 
133
 * The variables are listed with input variables preceding outputvariables
 
134
 * The end of each group is marked by an end marker.
 
135
 * per variable we list:
 
136
 * type - as defined in ecpgtype.h
 
137
 * value - where to store the data
 
138
 * varcharsize - length of string in case we have a stringvariable, else 0
 
139
 * arraysize - 0 for pointer (we don't know the size of the array),
 
140
 * 1 for simple variable, size for arrays
 
141
 * offset - offset between ith and (i+1)th entry in an array,
 
142
 * normally that means sizeof(type)
 
143
 * ind_type - type of indicator variable
 
144
 * ind_value - pointer to indicator variable
 
145
 * ind_varcharsize - empty
 
146
 * ind_arraysize -      arraysize of indicator array
 
147
 * ind_offset - indicator offset
 
148
 */
 
149
static bool
 
150
create_statement(int lineno, int compat, int force_indicator, struct connection * connection, struct statement ** stmt, char *query, va_list ap)
 
151
{
 
152
        struct variable **list = &((*stmt)->inlist);
 
153
        enum ECPGttype type;
 
154
 
 
155
        if (!(*stmt = (struct statement *) ECPGalloc(sizeof(struct statement), lineno)))
 
156
                return false;
 
157
 
 
158
        (*stmt)->command = query;
 
159
        (*stmt)->connection = connection;
 
160
        (*stmt)->lineno = lineno;
 
161
        (*stmt)->compat = compat;
 
162
        (*stmt)->force_indicator = force_indicator;
 
163
 
 
164
        list = &((*stmt)->inlist);
 
165
 
 
166
        type = va_arg(ap, enum ECPGttype);
 
167
 
 
168
        while (type != ECPGt_EORT)
 
169
        {
 
170
                if (type == ECPGt_EOIT)
 
171
                        list = &((*stmt)->outlist);
 
172
                else
 
173
                {
 
174
                        struct variable *var,
 
175
                                           *ptr;
 
176
 
 
177
                        if (!(var = (struct variable *) ECPGalloc(sizeof(struct variable), lineno)))
 
178
                                return false;
 
179
 
 
180
#if defined(__GNUC__) && (defined (__powerpc__) || defined(__AMD64__))
 
181
                        ECPGget_variable(ap, type, var, true);
 
182
#else
 
183
                        ECPGget_variable(&ap, type, var, true);
 
184
#endif
 
185
 
 
186
                        /* if variable is NULL, the statement hasn't been prepared */
 
187
                        if (var->pointer == NULL)
 
188
                        {
 
189
                                ECPGraise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, NULL);
 
190
                                ECPGfree(var);
 
191
                                return false;
 
192
                        }
 
193
 
 
194
                        for (ptr = *list; ptr && ptr->next; ptr = ptr->next);
 
195
 
 
196
                        if (ptr == NULL)
 
197
                                *list = var;
 
198
                        else
 
199
                                ptr->next = var;
 
200
                }
 
201
 
 
202
                type = va_arg(ap, enum ECPGttype);
 
203
        }
 
204
 
 
205
        return (true);
 
206
}
 
207
 
 
208
static void
 
209
free_variable(struct variable * var)
 
210
{
 
211
        struct variable *var_next;
 
212
 
 
213
        if (var == NULL)
 
214
                return;
 
215
        var_next = var->next;
 
216
        ECPGfree(var);
 
217
 
 
218
        while (var_next)
 
219
        {
 
220
                var = var_next;
 
221
                var_next = var->next;
 
222
                ECPGfree(var);
 
223
        }
 
224
}
 
225
 
 
226
static void
 
227
free_statement(struct statement * stmt)
 
228
{
 
229
        if (stmt == NULL)
 
230
                return;
 
231
        free_variable(stmt->inlist);
 
232
        free_variable(stmt->outlist);
 
233
        ECPGfree(stmt);
 
234
}
 
235
 
 
236
static char *
 
237
next_insert(char *text)
 
238
{
 
239
        char       *ptr = text;
 
240
        bool            string = false;
 
241
 
 
242
        for (; *ptr != '\0' && (*ptr != '?' || string); ptr++)
 
243
        {
 
244
                if (*ptr == '\\')               /* escape character */
 
245
                        ptr++;
 
246
                else if (*ptr == '\'')
 
247
                        string = string ? false : true;
 
248
        }
 
249
 
 
250
        return (*ptr == '\0') ? NULL : ptr;
 
251
}
 
252
 
 
253
static void
 
254
ECPGtypeinfocache_push(struct ECPGtype_information_cache ** cache, int oid, bool isarray, int lineno)
 
255
{
 
256
        struct ECPGtype_information_cache *new_entry
 
257
        = (struct ECPGtype_information_cache *) ECPGalloc(sizeof(struct ECPGtype_information_cache), lineno);
 
258
 
 
259
        new_entry->oid = oid;
 
260
        new_entry->isarray = isarray;
 
261
        new_entry->next = *cache;
 
262
        *cache = new_entry;
 
263
}
 
264
 
 
265
static enum ARRAY_TYPE
 
266
ECPGis_type_an_array(int type, const struct statement * stmt, const struct variable * var)
 
267
{
 
268
        char       *array_query;
 
269
        enum ARRAY_TYPE isarray = ECPG_ARRAY_NOT_SET;
 
270
        PGresult   *query;
 
271
        struct ECPGtype_information_cache *cache_entry;
 
272
 
 
273
        if ((stmt->connection->cache_head) == NULL)
 
274
        {
 
275
                /*
 
276
                 * Text like types are not an array for ecpg, but postgres counts
 
277
                 * them as an array. This define reminds you to not 'correct'
 
278
                 * these values.
 
279
                 */
 
280
#define not_an_array_in_ecpg ECPG_ARRAY_NONE
 
281
 
 
282
                /* populate cache with well known types to speed things up */
 
283
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), BOOLOID, ECPG_ARRAY_NONE, stmt->lineno);
 
284
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), BYTEAOID, ECPG_ARRAY_NONE, stmt->lineno);
 
285
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), CHAROID, ECPG_ARRAY_NONE, stmt->lineno);
 
286
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), NAMEOID, not_an_array_in_ecpg, stmt->lineno);
 
287
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT8OID, ECPG_ARRAY_NONE, stmt->lineno);
 
288
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT2OID, ECPG_ARRAY_NONE, stmt->lineno);
 
289
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT2VECTOROID, ECPG_ARRAY_VECTOR, stmt->lineno);
 
290
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT4OID, ECPG_ARRAY_NONE, stmt->lineno);
 
291
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), REGPROCOID, ECPG_ARRAY_NONE, stmt->lineno);
 
292
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), TEXTOID, ECPG_ARRAY_NONE, stmt->lineno);
 
293
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), OIDOID, ECPG_ARRAY_NONE, stmt->lineno);
 
294
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIDOID, ECPG_ARRAY_NONE, stmt->lineno);
 
295
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), XIDOID, ECPG_ARRAY_NONE, stmt->lineno);
 
296
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIDOID, ECPG_ARRAY_NONE, stmt->lineno);
 
297
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), OIDVECTOROID, ECPG_ARRAY_VECTOR, stmt->lineno);
 
298
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), POINTOID, ECPG_ARRAY_VECTOR, stmt->lineno);
 
299
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), LSEGOID, ECPG_ARRAY_VECTOR, stmt->lineno);
 
300
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), PATHOID, ECPG_ARRAY_NONE, stmt->lineno);
 
301
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), BOXOID, ECPG_ARRAY_VECTOR, stmt->lineno);
 
302
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), POLYGONOID, ECPG_ARRAY_NONE, stmt->lineno);
 
303
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), LINEOID, ECPG_ARRAY_VECTOR, stmt->lineno);
 
304
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), FLOAT4OID, ECPG_ARRAY_NONE, stmt->lineno);
 
305
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), FLOAT8OID, ECPG_ARRAY_NONE, stmt->lineno);
 
306
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), ABSTIMEOID, ECPG_ARRAY_NONE, stmt->lineno);
 
307
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), RELTIMEOID, ECPG_ARRAY_NONE, stmt->lineno);
 
308
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), TINTERVALOID, ECPG_ARRAY_NONE, stmt->lineno);
 
309
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), UNKNOWNOID, ECPG_ARRAY_NONE, stmt->lineno);
 
310
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIRCLEOID, ECPG_ARRAY_NONE, stmt->lineno);
 
311
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), CASHOID, ECPG_ARRAY_NONE, stmt->lineno);
 
312
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), INETOID, ECPG_ARRAY_NONE, stmt->lineno);
 
313
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIDROID, ECPG_ARRAY_NONE, stmt->lineno);
 
314
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), BPCHAROID, ECPG_ARRAY_NONE, stmt->lineno);
 
315
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), VARCHAROID, ECPG_ARRAY_NONE, stmt->lineno);
 
316
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), DATEOID, ECPG_ARRAY_NONE, stmt->lineno);
 
317
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMEOID, ECPG_ARRAY_NONE, stmt->lineno);
 
318
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMESTAMPOID, ECPG_ARRAY_NONE, stmt->lineno);
 
319
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMESTAMPTZOID, ECPG_ARRAY_NONE, stmt->lineno);
 
320
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), INTERVALOID, ECPG_ARRAY_NONE, stmt->lineno);
 
321
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMETZOID, ECPG_ARRAY_NONE, stmt->lineno);
 
322
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), ZPBITOID, ECPG_ARRAY_NONE, stmt->lineno);
 
323
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), VARBITOID, ECPG_ARRAY_NONE, stmt->lineno);
 
324
                ECPGtypeinfocache_push(&(stmt->connection->cache_head), NUMERICOID, ECPG_ARRAY_NONE, stmt->lineno);
 
325
        }
 
326
 
 
327
        for (cache_entry = (stmt->connection->cache_head); cache_entry != NULL; cache_entry = cache_entry->next)
 
328
        {
 
329
                if (cache_entry->oid == type)
 
330
                        return cache_entry->isarray;
 
331
        }
 
332
 
 
333
        array_query = (char *) ECPGalloc(strlen("select typlen from pg_type where oid= and typelem<>0") + 11, stmt->lineno);
 
334
        sprintf(array_query, "select typlen from pg_type where oid=%d and typelem<>0", type);
 
335
        query = PQexec(stmt->connection->connection, array_query);
 
336
        ECPGfree(array_query);
 
337
        if (PQresultStatus(query) == PGRES_TUPLES_OK)
 
338
        {
 
339
                if (PQntuples(query) == 0)
 
340
                        isarray = ECPG_ARRAY_NONE;
 
341
                else
 
342
                {
 
343
                        isarray = (atol((char *) PQgetvalue(query, 0, 0)) == -1) ? ECPG_ARRAY_ARRAY : ECPG_ARRAY_VECTOR;
 
344
                        if (ECPGDynamicType(type) == SQL3_CHARACTER ||
 
345
                                ECPGDynamicType(type) == SQL3_CHARACTER_VARYING)
 
346
                        {
 
347
                                /*
 
348
                                 * arrays of character strings are not yet implemented
 
349
                                 */
 
350
                                isarray = ECPG_ARRAY_NONE;
 
351
                        }
 
352
                }
 
353
        }
 
354
        PQclear(query);
 
355
        ECPGtypeinfocache_push(&(stmt->connection->cache_head), type, isarray, stmt->lineno);
 
356
        ECPGlog("ECPGis_type_an_array line %d: TYPE database: %d C: %d array: %s\n", stmt->lineno, type, var->type, isarray ? "Yes" : "No");
 
357
        return isarray;
 
358
}
 
359
 
 
360
 
 
361
bool
 
362
ECPGstore_result(const PGresult *results, int act_field,
 
363
                                 const struct statement * stmt, struct variable * var)
 
364
{
 
365
        enum ARRAY_TYPE isarray;
 
366
        int                     act_tuple,
 
367
                                ntuples = PQntuples(results);
 
368
        bool            status = true;
 
369
 
 
370
        isarray = ECPGis_type_an_array(PQftype(results, act_field), stmt, var);
 
371
 
 
372
        if (isarray == ECPG_ARRAY_NONE)
 
373
        {
 
374
                /*
 
375
                 * if we don't have enough space, we cannot read all tuples
 
376
                 */
 
377
                if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
 
378
                {
 
379
                        ECPGlog("ECPGstore_result line %d: Incorrect number of matches: %d don't fit into array of %d\n",
 
380
                                        stmt->lineno, ntuples, var->arrsize);
 
381
                        ECPGraise(stmt->lineno, INFORMIX_MODE(stmt->compat) ? ECPG_INFORMIX_SUBSELECT_NOT_ONE : ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
 
382
                        return false;
 
383
                }
 
384
        }
 
385
        else
 
386
        {
 
387
                /*
 
388
                 * since we read an array, the variable has to be an array too
 
389
                 */
 
390
                if (var->arrsize == 0)
 
391
                {
 
392
                        ECPGraise(stmt->lineno, ECPG_NO_ARRAY, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
 
393
                        return false;
 
394
                }
 
395
        }
 
396
 
 
397
        /*
 
398
         * allocate memory for NULL pointers
 
399
         */
 
400
        if ((var->arrsize == 0 || var->varcharsize == 0) && var->value == NULL)
 
401
        {
 
402
                int                     len = 0;
 
403
 
 
404
                switch (var->type)
 
405
                {
 
406
                        case ECPGt_char:
 
407
                        case ECPGt_unsigned_char:
 
408
                                if (!var->varcharsize && !var->arrsize)
 
409
                                {
 
410
                                        /* special mode for handling char**foo=0 */
 
411
                                        for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
 
412
                                                len += strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
 
413
                                        len *= var->offset; /* should be 1, but YMNK */
 
414
                                        len += (ntuples + 1) * sizeof(char *);
 
415
 
 
416
                                        ECPGlog("ECPGstore_result: line %d: allocating %d bytes for %d tuples (char**=0)",
 
417
                                                        stmt->lineno, len, ntuples);
 
418
                                }
 
419
                                else
 
420
                                {
 
421
                                        var->varcharsize = 0;
 
422
                                        /* check strlen for each tuple */
 
423
                                        for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
 
424
                                        {
 
425
                                                int                     len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
 
426
 
 
427
                                                if (len > var->varcharsize)
 
428
                                                        var->varcharsize = len;
 
429
                                        }
 
430
                                        var->offset *= var->varcharsize;
 
431
                                        len = var->offset * ntuples;
 
432
                                }
 
433
                                break;
 
434
                        case ECPGt_varchar:
 
435
                                len = ntuples * (var->varcharsize + sizeof(int));
 
436
                                break;
 
437
                        default:
 
438
                                len = var->offset * ntuples;
 
439
                                break;
 
440
                }
 
441
                var->value = (char *) ECPGalloc(len, stmt->lineno);
 
442
                *((char **) var->pointer) = var->value;
 
443
                ECPGadd_mem(var->value, stmt->lineno);
 
444
        }
 
445
 
 
446
        /* allocate indicator variable if needed */
 
447
        if ((var->ind_arrsize == 0 || var->ind_varcharsize == 0) && var->ind_value == NULL && var->ind_pointer != NULL)
 
448
        {
 
449
                int                     len = var->ind_offset * ntuples;
 
450
 
 
451
                var->ind_value = (char *) ECPGalloc(len, stmt->lineno);
 
452
                *((char **) var->ind_pointer) = var->ind_value;
 
453
                ECPGadd_mem(var->ind_value, stmt->lineno);
 
454
        }
 
455
 
 
456
        /* fill the variable with the tuple(s) */
 
457
        if (!var->varcharsize && !var->arrsize &&
 
458
                (var->type == ECPGt_char || var->type == ECPGt_unsigned_char))
 
459
        {
 
460
                /* special mode for handling char**foo=0 */
 
461
 
 
462
                /* filling the array of (char*)s */
 
463
                char      **current_string = (char **) var->value;
 
464
 
 
465
                /* storing the data (after the last array element) */
 
466
                char       *current_data_location = (char *) &current_string[ntuples + 1];
 
467
 
 
468
                for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
 
469
                {
 
470
                        int                     len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
 
471
 
 
472
                        if (!ECPGget_data(results, act_tuple, act_field, stmt->lineno,
 
473
                                                 var->type, var->ind_type, current_data_location,
 
474
                                                          var->ind_value, len, 0, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
 
475
                                status = false;
 
476
                        else
 
477
                        {
 
478
                                *current_string = current_data_location;
 
479
                                current_data_location += len;
 
480
                                current_string++;
 
481
                        }
 
482
                }
 
483
 
 
484
                /* terminate the list */
 
485
                *current_string = NULL;
 
486
        }
 
487
        else
 
488
        {
 
489
                for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
 
490
                {
 
491
                        if (!ECPGget_data(results, act_tuple, act_field, stmt->lineno,
 
492
                                                          var->type, var->ind_type, var->value,
 
493
                                                          var->ind_value, var->varcharsize, var->offset, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
 
494
                                status = false;
 
495
                }
 
496
        }
 
497
        return status;
 
498
}
 
499
 
 
500
bool
 
501
ECPGstore_input(const int lineno, const bool force_indicator, const struct variable * var,
 
502
                                const char **tobeinserted_p, bool *malloced_p)
 
503
{
 
504
        char       *mallocedval = NULL;
 
505
        char       *newcopy = NULL;
 
506
 
 
507
        /*
 
508
         * arrays are not possible unless the attribute is an array too FIXME:
 
509
         * we do not know if the attribute is an array here
 
510
         */
 
511
#if 0
 
512
        if (var->arrsize > 1 &&...)
 
513
        {
 
514
                ECPGraise(lineno, ECPG_ARRAY_INSERT, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
 
515
                return false;
 
516
        }
 
517
#endif
 
518
 
 
519
        /*
 
520
         * Some special treatment is needed for records since we want their
 
521
         * contents to arrive in a comma-separated list on insert (I think).
 
522
         */
 
523
 
 
524
        *malloced_p = false;
 
525
        *tobeinserted_p = "";
 
526
 
 
527
        /* check for null value and set input buffer accordingly */
 
528
        switch (var->ind_type)
 
529
        {
 
530
                case ECPGt_short:
 
531
                case ECPGt_unsigned_short:
 
532
                        if (*(short *) var->ind_value < 0)
 
533
                                *tobeinserted_p = "null";
 
534
                        break;
 
535
                case ECPGt_int:
 
536
                case ECPGt_unsigned_int:
 
537
                        if (*(int *) var->ind_value < 0)
 
538
                                *tobeinserted_p = "null";
 
539
                        break;
 
540
                case ECPGt_long:
 
541
                case ECPGt_unsigned_long:
 
542
                        if (*(long *) var->ind_value < 0L)
 
543
                                *tobeinserted_p = "null";
 
544
                        break;
 
545
#ifdef HAVE_LONG_LONG_INT_64
 
546
                case ECPGt_long_long:
 
547
                case ECPGt_unsigned_long_long:
 
548
                        if (*(long long int *) var->ind_value < (long long) 0)
 
549
                                *tobeinserted_p = "null";
 
550
                        break;
 
551
#endif   /* HAVE_LONG_LONG_INT_64 */
 
552
                case ECPGt_NO_INDICATOR:
 
553
                        if (force_indicator == false)
 
554
                        {
 
555
                                if (ECPGis_noind_null(var->type, var->value))
 
556
                                        *tobeinserted_p = "null";
 
557
                        }
 
558
                        break;
 
559
                default:
 
560
                        break;
 
561
        }
 
562
        if (**tobeinserted_p == '\0')
 
563
        {
 
564
                switch (var->type)
 
565
                {
 
566
                                int                     element;
 
567
 
 
568
                        case ECPGt_short:
 
569
                                if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
 
570
                                        return false;
 
571
 
 
572
                                if (var->arrsize > 1)
 
573
                                {
 
574
                                        strcpy(mallocedval, "array [");
 
575
 
 
576
                                        for (element = 0; element < var->arrsize; element++)
 
577
                                                sprintf(mallocedval + strlen(mallocedval), "%hd,", ((short *) var->value)[element]);
 
578
 
 
579
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
580
                                }
 
581
                                else
 
582
                                        sprintf(mallocedval, "%hd", *((short *) var->value));
 
583
 
 
584
                                *tobeinserted_p = mallocedval;
 
585
                                *malloced_p = true;
 
586
                                break;
 
587
 
 
588
                        case ECPGt_int:
 
589
                                if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
 
590
                                        return false;
 
591
 
 
592
                                if (var->arrsize > 1)
 
593
                                {
 
594
                                        strcpy(mallocedval, "array [");
 
595
 
 
596
                                        for (element = 0; element < var->arrsize; element++)
 
597
                                                sprintf(mallocedval + strlen(mallocedval), "%d,", ((int *) var->value)[element]);
 
598
 
 
599
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
600
                                }
 
601
                                else
 
602
                                        sprintf(mallocedval, "%d", *((int *) var->value));
 
603
 
 
604
                                *tobeinserted_p = mallocedval;
 
605
                                *malloced_p = true;
 
606
                                break;
 
607
 
 
608
                        case ECPGt_unsigned_short:
 
609
                                if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
 
610
                                        return false;
 
611
 
 
612
                                if (var->arrsize > 1)
 
613
                                {
 
614
                                        strcpy(mallocedval, "array [");
 
615
 
 
616
                                        for (element = 0; element < var->arrsize; element++)
 
617
                                                sprintf(mallocedval + strlen(mallocedval), "%hu,", ((unsigned short *) var->value)[element]);
 
618
 
 
619
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
620
                                }
 
621
                                else
 
622
                                        sprintf(mallocedval, "%hu", *((unsigned short *) var->value));
 
623
 
 
624
                                *tobeinserted_p = mallocedval;
 
625
                                *malloced_p = true;
 
626
                                break;
 
627
 
 
628
                        case ECPGt_unsigned_int:
 
629
                                if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
 
630
                                        return false;
 
631
 
 
632
                                if (var->arrsize > 1)
 
633
                                {
 
634
                                        strcpy(mallocedval, "array [");
 
635
 
 
636
                                        for (element = 0; element < var->arrsize; element++)
 
637
                                                sprintf(mallocedval + strlen(mallocedval), "%u,", ((unsigned int *) var->value)[element]);
 
638
 
 
639
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
640
                                }
 
641
                                else
 
642
                                        sprintf(mallocedval, "%u", *((unsigned int *) var->value));
 
643
 
 
644
                                *tobeinserted_p = mallocedval;
 
645
                                *malloced_p = true;
 
646
                                break;
 
647
 
 
648
                        case ECPGt_long:
 
649
                                if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
 
650
                                        return false;
 
651
 
 
652
                                if (var->arrsize > 1)
 
653
                                {
 
654
                                        strcpy(mallocedval, "array [");
 
655
 
 
656
                                        for (element = 0; element < var->arrsize; element++)
 
657
                                                sprintf(mallocedval + strlen(mallocedval), "%ld,", ((long *) var->value)[element]);
 
658
 
 
659
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
660
                                }
 
661
                                else
 
662
                                        sprintf(mallocedval, "%ld", *((long *) var->value));
 
663
 
 
664
                                *tobeinserted_p = mallocedval;
 
665
                                *malloced_p = true;
 
666
                                break;
 
667
 
 
668
                        case ECPGt_unsigned_long:
 
669
                                if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
 
670
                                        return false;
 
671
 
 
672
                                if (var->arrsize > 1)
 
673
                                {
 
674
                                        strcpy(mallocedval, "array [");
 
675
 
 
676
                                        for (element = 0; element < var->arrsize; element++)
 
677
                                                sprintf(mallocedval + strlen(mallocedval), "%lu,", ((unsigned long *) var->value)[element]);
 
678
 
 
679
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
680
                                }
 
681
                                else
 
682
                                        sprintf(mallocedval, "%lu", *((unsigned long *) var->value));
 
683
 
 
684
                                *tobeinserted_p = mallocedval;
 
685
                                *malloced_p = true;
 
686
                                break;
 
687
#ifdef HAVE_LONG_LONG_INT_64
 
688
                        case ECPGt_long_long:
 
689
                                if (!(mallocedval = ECPGalloc(var->arrsize * 30, lineno)))
 
690
                                        return false;
 
691
 
 
692
                                if (var->arrsize > 1)
 
693
                                {
 
694
                                        strcpy(mallocedval, "array [");
 
695
 
 
696
                                        for (element = 0; element < var->arrsize; element++)
 
697
                                                sprintf(mallocedval + strlen(mallocedval), "%lld,", ((long long *) var->value)[element]);
 
698
 
 
699
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
700
                                }
 
701
                                else
 
702
                                        sprintf(mallocedval, "%lld", *((long long *) var->value));
 
703
 
 
704
                                *tobeinserted_p = mallocedval;
 
705
                                *malloced_p = true;
 
706
                                break;
 
707
 
 
708
                        case ECPGt_unsigned_long_long:
 
709
                                if (!(mallocedval = ECPGalloc(var->arrsize * 30, lineno)))
 
710
                                        return false;
 
711
 
 
712
                                if (var->arrsize > 1)
 
713
                                {
 
714
                                        strcpy(mallocedval, "array [");
 
715
 
 
716
                                        for (element = 0; element < var->arrsize; element++)
 
717
                                                sprintf(mallocedval + strlen(mallocedval), "%llu,", ((unsigned long long *) var->value)[element]);
 
718
 
 
719
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
720
                                }
 
721
                                else
 
722
                                        sprintf(mallocedval, "%llu", *((unsigned long long *) var->value));
 
723
 
 
724
                                *tobeinserted_p = mallocedval;
 
725
                                *malloced_p = true;
 
726
                                break;
 
727
#endif   /* HAVE_LONG_LONG_INT_64 */
 
728
                        case ECPGt_float:
 
729
                                if (!(mallocedval = ECPGalloc(var->arrsize * 25, lineno)))
 
730
                                        return false;
 
731
 
 
732
                                if (var->arrsize > 1)
 
733
                                {
 
734
                                        strcpy(mallocedval, "array [");
 
735
 
 
736
                                        for (element = 0; element < var->arrsize; element++)
 
737
                                                sprintf(mallocedval + strlen(mallocedval), "%.14g,", ((float *) var->value)[element]);
 
738
 
 
739
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
740
                                }
 
741
                                else
 
742
                                        sprintf(mallocedval, "%.14g", *((float *) var->value));
 
743
 
 
744
                                *tobeinserted_p = mallocedval;
 
745
                                *malloced_p = true;
 
746
                                break;
 
747
 
 
748
                        case ECPGt_double:
 
749
                                if (!(mallocedval = ECPGalloc(var->arrsize * 25, lineno)))
 
750
                                        return false;
 
751
 
 
752
                                if (var->arrsize > 1)
 
753
                                {
 
754
                                        strcpy(mallocedval, "array [");
 
755
 
 
756
                                        for (element = 0; element < var->arrsize; element++)
 
757
                                                sprintf(mallocedval + strlen(mallocedval), "%.14g,", ((double *) var->value)[element]);
 
758
 
 
759
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
760
                                }
 
761
                                else
 
762
                                        sprintf(mallocedval, "%.14g", *((double *) var->value));
 
763
 
 
764
                                *tobeinserted_p = mallocedval;
 
765
                                *malloced_p = true;
 
766
                                break;
 
767
 
 
768
                        case ECPGt_bool:
 
769
                                if (!(mallocedval = ECPGalloc(var->arrsize + sizeof("array []"), lineno)))
 
770
                                        return false;
 
771
 
 
772
                                if (var->arrsize > 1)
 
773
                                {
 
774
                                        strcpy(mallocedval, "array [");
 
775
 
 
776
                                        if (var->offset == sizeof(char))
 
777
                                                for (element = 0; element < var->arrsize; element++)
 
778
                                                        sprintf(mallocedval + strlen(mallocedval), "%c,", (((char *) var->value)[element]) ? 't' : 'f');
 
779
 
 
780
                                        /*
 
781
                                         * this is necessary since sizeof(C++'s
 
782
                                         * bool)==sizeof(int)
 
783
                                         */
 
784
                                        else if (var->offset == sizeof(int))
 
785
                                                for (element = 0; element < var->arrsize; element++)
 
786
                                                        sprintf(mallocedval + strlen(mallocedval), "%c,", (((int *) var->value)[element]) ? 't' : 'f');
 
787
                                        else
 
788
                                                ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, "different size");
 
789
 
 
790
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
791
                                }
 
792
                                else
 
793
                                {
 
794
                                        if (var->offset == sizeof(char))
 
795
                                                sprintf(mallocedval, "'%c'", (*((char *) var->value)) ? 't' : 'f');
 
796
                                        else if (var->offset == sizeof(int))
 
797
                                                sprintf(mallocedval, "'%c'", (*((int *) var->value)) ? 't' : 'f');
 
798
                                        else
 
799
                                                ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, "different size");
 
800
                                }
 
801
 
 
802
                                *tobeinserted_p = mallocedval;
 
803
                                *malloced_p = true;
 
804
                                break;
 
805
 
 
806
                        case ECPGt_char:
 
807
                        case ECPGt_unsigned_char:
 
808
                                {
 
809
                                        /* set slen to string length if type is char * */
 
810
                                        int                     slen = (var->varcharsize == 0) ? strlen((char *) var->value) : var->varcharsize;
 
811
 
 
812
                                        if (!(newcopy = ECPGalloc(slen + 1, lineno)))
 
813
                                                return false;
 
814
 
 
815
                                        strncpy(newcopy, (char *) var->value, slen);
 
816
                                        newcopy[slen] = '\0';
 
817
 
 
818
                                        mallocedval = quote_postgres(newcopy, lineno);
 
819
                                        if (!mallocedval)
 
820
                                                return false;
 
821
 
 
822
                                        ECPGfree(newcopy);
 
823
 
 
824
                                        *tobeinserted_p = mallocedval;
 
825
                                        *malloced_p = true;
 
826
                                }
 
827
                                break;
 
828
                        case ECPGt_const:
 
829
                        case ECPGt_char_variable:
 
830
                                {
 
831
                                        int                     slen = strlen((char *) var->value);
 
832
 
 
833
                                        if (!(mallocedval = ECPGalloc(slen + 1, lineno)))
 
834
                                                return false;
 
835
 
 
836
                                        strncpy(mallocedval, (char *) var->value, slen);
 
837
                                        mallocedval[slen] = '\0';
 
838
 
 
839
                                        *tobeinserted_p = mallocedval;
 
840
                                        *malloced_p = true;
 
841
                                }
 
842
                                break;
 
843
                        case ECPGt_varchar:
 
844
                                {
 
845
                                        struct ECPGgeneric_varchar *variable =
 
846
                                        (struct ECPGgeneric_varchar *) (var->value);
 
847
 
 
848
                                        if (!(newcopy = (char *) ECPGalloc(variable->len + 1, lineno)))
 
849
                                                return false;
 
850
 
 
851
                                        strncpy(newcopy, variable->arr, variable->len);
 
852
                                        newcopy[variable->len] = '\0';
 
853
 
 
854
                                        mallocedval = quote_postgres(newcopy, lineno);
 
855
                                        if (!mallocedval)
 
856
                                                return false;
 
857
 
 
858
                                        ECPGfree(newcopy);
 
859
 
 
860
                                        *tobeinserted_p = mallocedval;
 
861
                                        *malloced_p = true;
 
862
                                }
 
863
                                break;
 
864
 
 
865
                        case ECPGt_decimal:
 
866
                        case ECPGt_numeric:
 
867
                                {
 
868
                                        char       *str = NULL;
 
869
                                        int                     slen;
 
870
                                        numeric    *nval = PGTYPESnumeric_new();
 
871
 
 
872
                                        if (var->arrsize > 1)
 
873
                                        {
 
874
                                                for (element = 0; element < var->arrsize; element++)
 
875
                                                {
 
876
                                                        if (var->type == ECPGt_numeric)
 
877
                                                                PGTYPESnumeric_copy((numeric *) ((var + var->offset * element)->value), nval);
 
878
                                                        else
 
879
                                                                PGTYPESnumeric_from_decimal((decimal *) ((var + var->offset * element)->value), nval);
 
880
 
 
881
                                                        str = PGTYPESnumeric_to_asc(nval, nval->dscale);
 
882
                                                        PGTYPESnumeric_free(nval);
 
883
                                                        slen = strlen(str);
 
884
 
 
885
                                                        if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [] "), lineno)))
 
886
                                                                return false;
 
887
 
 
888
                                                        if (!element)
 
889
                                                                strcpy(mallocedval, "array [");
 
890
 
 
891
                                                        strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
 
892
                                                        strcpy(mallocedval + strlen(mallocedval), ",");
 
893
                                                }
 
894
                                                strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
895
                                        }
 
896
                                        else
 
897
                                        {
 
898
                                                if (var->type == ECPGt_numeric)
 
899
                                                        PGTYPESnumeric_copy((numeric *) (var->value), nval);
 
900
                                                else
 
901
                                                        PGTYPESnumeric_from_decimal((decimal *) (var->value), nval);
 
902
 
 
903
                                                str = PGTYPESnumeric_to_asc(nval, nval->dscale);
 
904
 
 
905
                                                PGTYPESnumeric_free(nval);
 
906
                                                slen = strlen(str);
 
907
 
 
908
                                                if (!(mallocedval = ECPGalloc(slen + 1, lineno)))
 
909
                                                        return false;
 
910
 
 
911
                                                strncpy(mallocedval, str, slen);
 
912
                                                mallocedval[slen] = '\0';
 
913
                                        }
 
914
 
 
915
                                        *tobeinserted_p = mallocedval;
 
916
                                        *malloced_p = true;
 
917
                                        free(str);
 
918
                                }
 
919
                                break;
 
920
 
 
921
                        case ECPGt_interval:
 
922
                                {
 
923
                                        char       *str = NULL;
 
924
                                        int                     slen;
 
925
 
 
926
                                        if (var->arrsize > 1)
 
927
                                        {
 
928
                                                for (element = 0; element < var->arrsize; element++)
 
929
                                                {
 
930
                                                        str = quote_postgres(PGTYPESinterval_to_asc((interval *) ((var + var->offset * element)->value)), lineno);
 
931
                                                        slen = strlen(str);
 
932
 
 
933
                                                        if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [],interval "), lineno)))
 
934
                                                                return false;
 
935
 
 
936
                                                        if (!element)
 
937
                                                                strcpy(mallocedval, "array [");
 
938
 
 
939
                                                        strcpy(mallocedval + strlen(mallocedval), "interval ");
 
940
                                                        strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
 
941
                                                        strcpy(mallocedval + strlen(mallocedval), ",");
 
942
                                                }
 
943
                                                strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
944
                                        }
 
945
                                        else
 
946
                                        {
 
947
                                                str = quote_postgres(PGTYPESinterval_to_asc((interval *) (var->value)), lineno);
 
948
                                                slen = strlen(str);
 
949
 
 
950
                                                if (!(mallocedval = ECPGalloc(slen + sizeof("interval ") + 1, lineno)))
 
951
                                                        return false;
 
952
 
 
953
                                                strcpy(mallocedval, "interval ");
 
954
                                                /* also copy trailing '\0' */
 
955
                                                strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
 
956
                                        }
 
957
 
 
958
                                        *tobeinserted_p = mallocedval;
 
959
                                        *malloced_p = true;
 
960
                                        free(str);
 
961
                                }
 
962
                                break;
 
963
 
 
964
                        case ECPGt_date:
 
965
                                {
 
966
                                        char       *str = NULL;
 
967
                                        int                     slen;
 
968
 
 
969
                                        if (var->arrsize > 1)
 
970
                                        {
 
971
                                                for (element = 0; element < var->arrsize; element++)
 
972
                                                {
 
973
                                                        str = quote_postgres(PGTYPESdate_to_asc(*(date *) ((var + var->offset * element)->value)), lineno);
 
974
                                                        slen = strlen(str);
 
975
 
 
976
                                                        if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [],date "), lineno)))
 
977
                                                                return false;
 
978
 
 
979
                                                        if (!element)
 
980
                                                                strcpy(mallocedval, "array [");
 
981
 
 
982
                                                        strcpy(mallocedval + strlen(mallocedval), "date ");
 
983
                                                        strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
 
984
                                                        strcpy(mallocedval + strlen(mallocedval), ",");
 
985
                                                }
 
986
                                                strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
987
                                        }
 
988
                                        else
 
989
                                        {
 
990
                                                str = quote_postgres(PGTYPESdate_to_asc(*(date *) (var->value)), lineno);
 
991
                                                slen = strlen(str);
 
992
 
 
993
                                                if (!(mallocedval = ECPGalloc(slen + sizeof("date ") + 1, lineno)))
 
994
                                                        return false;
 
995
 
 
996
                                                strcpy(mallocedval, "date ");
 
997
                                                /* also copy trailing '\0' */
 
998
                                                strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
 
999
                                        }
 
1000
 
 
1001
                                        *tobeinserted_p = mallocedval;
 
1002
                                        *malloced_p = true;
 
1003
                                        free(str);
 
1004
                                }
 
1005
                                break;
 
1006
 
 
1007
                        case ECPGt_timestamp:
 
1008
                                {
 
1009
                                        char       *str = NULL;
 
1010
                                        int                     slen;
 
1011
 
 
1012
                                        if (var->arrsize > 1)
 
1013
                                        {
 
1014
                                                for (element = 0; element < var->arrsize; element++)
 
1015
                                                {
 
1016
                                                        str = quote_postgres(PGTYPEStimestamp_to_asc(*(timestamp *) ((var + var->offset * element)->value)), lineno);
 
1017
                                                        slen = strlen(str);
 
1018
 
 
1019
                                                        if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [], timestamp "), lineno)))
 
1020
                                                                return false;
 
1021
 
 
1022
                                                        if (!element)
 
1023
                                                                strcpy(mallocedval, "array [");
 
1024
 
 
1025
                                                        strcpy(mallocedval + strlen(mallocedval), "timestamp ");
 
1026
                                                        strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
 
1027
                                                        strcpy(mallocedval + strlen(mallocedval), ",");
 
1028
                                                }
 
1029
                                                strcpy(mallocedval + strlen(mallocedval) - 1, "]");
 
1030
                                        }
 
1031
                                        else
 
1032
                                        {
 
1033
                                                str = quote_postgres(PGTYPEStimestamp_to_asc(*(timestamp *) (var->value)), lineno);
 
1034
                                                slen = strlen(str);
 
1035
 
 
1036
                                                if (!(mallocedval = ECPGalloc(slen + sizeof("timestamp") + 1, lineno)))
 
1037
                                                        return false;
 
1038
 
 
1039
                                                strcpy(mallocedval, "timestamp ");
 
1040
                                                /* also copy trailing '\0' */
 
1041
                                                strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
 
1042
                                        }
 
1043
 
 
1044
                                        *tobeinserted_p = mallocedval;
 
1045
                                        *malloced_p = true;
 
1046
                                        free(str);
 
1047
                                }
 
1048
                                break;
 
1049
 
 
1050
                        case ECPGt_descriptor:
 
1051
                                break;
 
1052
 
 
1053
                        default:
 
1054
                                /* Not implemented yet */
 
1055
                                ECPGraise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, (char *) ECPGtype_name(var->type));
 
1056
                                return false;
 
1057
                                break;
 
1058
                }
 
1059
        }
 
1060
        return true;
 
1061
}
 
1062
 
 
1063
static bool
 
1064
ECPGexecute(struct statement * stmt)
 
1065
{
 
1066
        bool            status = false;
 
1067
        char       *copiedquery;
 
1068
        char       *cmdstat;
 
1069
        PGresult   *results;
 
1070
        PGnotify   *notify;
 
1071
        struct variable *var;
 
1072
        int                     desc_counter = 0;
 
1073
 
 
1074
        copiedquery = ECPGstrdup(stmt->command, stmt->lineno);
 
1075
 
 
1076
        /*
 
1077
         * Now, if the type is one of the fill in types then we take the
 
1078
         * argument and enter that in the string at the first %s position.
 
1079
         * Then if there are any more fill in types we fill in at the next and
 
1080
         * so on.
 
1081
         */
 
1082
        var = stmt->inlist;
 
1083
 
 
1084
        while (var)
 
1085
        {
 
1086
                char       *newcopy = NULL;
 
1087
                const char *tobeinserted;
 
1088
                char       *p;
 
1089
                bool            malloced = FALSE;
 
1090
                int                     hostvarl = 0;
 
1091
 
 
1092
                tobeinserted = NULL;
 
1093
 
 
1094
                /*
 
1095
                 * A descriptor is a special case since it contains many variables
 
1096
                 * but is listed only once.
 
1097
                 */
 
1098
                if (var->type == ECPGt_descriptor)
 
1099
                {
 
1100
                        /*
 
1101
                         * We create an additional variable list here, so the same
 
1102
                         * logic applies.
 
1103
                         */
 
1104
                        struct variable desc_inlist;
 
1105
                        struct descriptor *desc;
 
1106
                        struct descriptor_item *desc_item;
 
1107
 
 
1108
                        for (desc = all_descriptors; desc; desc = desc->next)
 
1109
                        {
 
1110
                                if (strcmp(var->pointer, desc->name) == 0)
 
1111
                                        break;
 
1112
                        }
 
1113
 
 
1114
                        if (desc == NULL)
 
1115
                        {
 
1116
                                ECPGraise(stmt->lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, var->pointer);
 
1117
                                return false;
 
1118
                        }
 
1119
 
 
1120
                        desc_counter++;
 
1121
                        if (desc->count < 0 || desc->count >= desc_counter)
 
1122
                        {
 
1123
                                for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
 
1124
                                {
 
1125
                                        if (desc_item->num == desc_counter)
 
1126
                                        {
 
1127
                                                desc_inlist.type = ECPGt_char;
 
1128
                                                desc_inlist.value = desc_item->data;
 
1129
                                                desc_inlist.pointer = &(desc_item->data);
 
1130
                                                desc_inlist.varcharsize = strlen(desc_item->data);
 
1131
                                                desc_inlist.arrsize = 1;
 
1132
                                                desc_inlist.offset = 0;
 
1133
                                                if (!desc_item->indicator)
 
1134
                                                {
 
1135
                                                        desc_inlist.ind_type = ECPGt_NO_INDICATOR;
 
1136
                                                        desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
 
1137
                                                        desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
 
1138
                                                }
 
1139
                                                else
 
1140
                                                {
 
1141
                                                        desc_inlist.ind_type = ECPGt_int;
 
1142
                                                        desc_inlist.ind_value = &(desc_item->indicator);
 
1143
                                                        desc_inlist.ind_pointer = &(desc_inlist.ind_value);
 
1144
                                                        desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
 
1145
                                                        desc_inlist.ind_offset = 0;
 
1146
                                                }
 
1147
                                                if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, &malloced))
 
1148
                                                        return false;
 
1149
 
 
1150
                                                break;
 
1151
                                        }
 
1152
                                }
 
1153
 
 
1154
                                if (!desc_item) /* no more entries found in descriptor */
 
1155
                                        desc_counter = 0;
 
1156
                        }
 
1157
                        else
 
1158
                                desc_counter = 0;
 
1159
                }
 
1160
                else
 
1161
                {
 
1162
                        if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, &malloced))
 
1163
                                return false;
 
1164
                }
 
1165
 
 
1166
                if (tobeinserted)
 
1167
                {
 
1168
                        /*
 
1169
                         * Now tobeinserted points to an area that is to be inserted
 
1170
                         * at the first %s
 
1171
                         */
 
1172
                        if (!(newcopy = (char *) ECPGalloc(strlen(copiedquery) + strlen(tobeinserted) + 1, stmt->lineno)))
 
1173
                                return false;
 
1174
 
 
1175
                        strcpy(newcopy, copiedquery);
 
1176
                        if ((p = next_insert(newcopy + hostvarl)) == NULL)
 
1177
                        {
 
1178
                                /*
 
1179
                                 * We have an argument but we dont have the matched up
 
1180
                                 * string in the string
 
1181
                                 */
 
1182
                                ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
 
1183
                                return false;
 
1184
                        }
 
1185
                        else
 
1186
                        {
 
1187
                                strcpy(p, tobeinserted);
 
1188
                                hostvarl = strlen(newcopy);
 
1189
 
 
1190
                                /*
 
1191
                                 * The strange thing in the second argument is the rest of
 
1192
                                 * the string from the old string
 
1193
                                 */
 
1194
                                strcat(newcopy,
 
1195
                                           copiedquery
 
1196
                                           + (p - newcopy)
 
1197
                                           + sizeof("?") - 1 /* don't count the '\0' */ );
 
1198
                        }
 
1199
 
 
1200
                        /*
 
1201
                         * Now everything is safely copied to the newcopy. Lets free
 
1202
                         * the oldcopy and let the copiedquery get the var->value from
 
1203
                         * the newcopy.
 
1204
                         */
 
1205
                        if (malloced)
 
1206
                        {
 
1207
                                ECPGfree((char *) tobeinserted);
 
1208
                                tobeinserted = NULL;
 
1209
                        }
 
1210
 
 
1211
                        ECPGfree(copiedquery);
 
1212
                        copiedquery = newcopy;
 
1213
                }
 
1214
 
 
1215
                if (desc_counter == 0)
 
1216
                        var = var->next;
 
1217
        }
 
1218
 
 
1219
        /* Check if there are unmatched things left. */
 
1220
        if (next_insert(copiedquery) != NULL)
 
1221
        {
 
1222
                ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
 
1223
                return false;
 
1224
        }
 
1225
 
 
1226
        /* Now the request is built. */
 
1227
 
 
1228
        if (stmt->connection->committed && !stmt->connection->autocommit)
 
1229
        {
 
1230
                if ((results = PQexec(stmt->connection->connection, "begin transaction")) == NULL)
 
1231
                {
 
1232
                        ECPGraise(stmt->lineno, ECPG_TRANS, ECPG_SQLSTATE_TRANSACTION_RESOLUTION_UNKNOWN, NULL);
 
1233
                        return false;
 
1234
                }
 
1235
                PQclear(results);
 
1236
                stmt->connection->committed = false;
 
1237
        }
 
1238
 
 
1239
        ECPGlog("ECPGexecute line %d: QUERY: %s on connection %s\n", stmt->lineno, copiedquery, stmt->connection->name);
 
1240
        results = PQexec(stmt->connection->connection, copiedquery);
 
1241
        ECPGfree(copiedquery);
 
1242
 
 
1243
        if (results == NULL)
 
1244
        {
 
1245
                ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno, PQerrorMessage(stmt->connection->connection));
 
1246
                ECPGraise_backend(stmt->lineno, NULL, stmt->connection->connection, stmt->compat);
 
1247
        }
 
1248
        else
 
1249
 
 
1250
                /*
 
1251
                 * note: since some of the following code is duplicated in
 
1252
                 * descriptor.c it should go into a separate function
 
1253
                 */
 
1254
        {
 
1255
                bool            clear_result = TRUE;
 
1256
                struct sqlca_t *sqlca = ECPGget_sqlca();
 
1257
 
 
1258
                var = stmt->outlist;
 
1259
                switch (PQresultStatus(results))
 
1260
                {
 
1261
                                int                     nfields,
 
1262
                                                        ntuples,
 
1263
                                                        act_field;
 
1264
 
 
1265
                        case PGRES_TUPLES_OK:
 
1266
                                nfields = PQnfields(results);
 
1267
                                sqlca->sqlerrd[2] = ntuples = PQntuples(results);
 
1268
                                ECPGlog("ECPGexecute line %d: Correctly got %d tuples with %d fields\n", stmt->lineno, ntuples, nfields);
 
1269
                                status = true;
 
1270
 
 
1271
                                if (ntuples < 1)
 
1272
                                {
 
1273
                                        if (ntuples)
 
1274
                                                ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d\n",
 
1275
                                                                stmt->lineno, ntuples);
 
1276
                                        ECPGraise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
 
1277
                                        status = false;
 
1278
                                        break;
 
1279
                                }
 
1280
 
 
1281
                                if (var != NULL && var->type == ECPGt_descriptor)
 
1282
                                {
 
1283
                                        PGresult  **resultpp = ECPGdescriptor_lvalue(stmt->lineno, (const char *) var->pointer);
 
1284
 
 
1285
                                        if (resultpp == NULL)
 
1286
                                                status = false;
 
1287
                                        else
 
1288
                                        {
 
1289
                                                if (*resultpp)
 
1290
                                                        PQclear(*resultpp);
 
1291
                                                *resultpp = results;
 
1292
                                                clear_result = FALSE;
 
1293
                                                ECPGlog("ECPGexecute putting result (%d tuples) into descriptor '%s'\n", PQntuples(results), (const char *) var->pointer);
 
1294
                                        }
 
1295
                                        var = var->next;
 
1296
                                }
 
1297
                                else
 
1298
                                        for (act_field = 0; act_field < nfields && status; act_field++)
 
1299
                                        {
 
1300
                                                if (var != NULL)
 
1301
                                                {
 
1302
                                                        status = ECPGstore_result(results, act_field, stmt, var);
 
1303
                                                        var = var->next;
 
1304
                                                }
 
1305
                                                else if (!INFORMIX_MODE(stmt->compat))
 
1306
                                                {
 
1307
                                                        ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
 
1308
                                                        return (false);
 
1309
                                                }
 
1310
                                        }
 
1311
 
 
1312
                                if (status && var != NULL)
 
1313
                                {
 
1314
                                        ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
 
1315
                                        status = false;
 
1316
                                }
 
1317
 
 
1318
                                break;
 
1319
                        case PGRES_EMPTY_QUERY:
 
1320
                                /* do nothing */
 
1321
                                ECPGraise(stmt->lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
 
1322
                                break;
 
1323
                        case PGRES_COMMAND_OK:
 
1324
                                status = true;
 
1325
                                cmdstat = PQcmdStatus(results);
 
1326
                                sqlca->sqlerrd[1] = PQoidValue(results);
 
1327
                                sqlca->sqlerrd[2] = atol(PQcmdTuples(results));
 
1328
                                ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, cmdstat);
 
1329
                                if (stmt->compat != ECPG_COMPAT_INFORMIX_SE &&
 
1330
                                        !sqlca->sqlerrd[2] &&
 
1331
                                        (!strncmp(cmdstat, "UPDATE", 6)
 
1332
                                         || !strncmp(cmdstat, "INSERT", 6)
 
1333
                                         || !strncmp(cmdstat, "DELETE", 6)))
 
1334
                                        ECPGraise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
 
1335
                                break;
 
1336
                        case PGRES_NONFATAL_ERROR:
 
1337
                        case PGRES_FATAL_ERROR:
 
1338
                        case PGRES_BAD_RESPONSE:
 
1339
                                ECPGlog("ECPGexecute line %d: Error: %s", stmt->lineno, PQresultErrorMessage(results));
 
1340
                                ECPGraise_backend(stmt->lineno, results, stmt->connection->connection, stmt->compat);
 
1341
                                status = false;
 
1342
                                break;
 
1343
                        case PGRES_COPY_OUT:
 
1344
                                ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", stmt->lineno);
 
1345
                                PQendcopy(stmt->connection->connection);
 
1346
                                break;
 
1347
                        case PGRES_COPY_IN:
 
1348
                                ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", stmt->lineno);
 
1349
                                PQendcopy(stmt->connection->connection);
 
1350
                                break;
 
1351
                        default:
 
1352
                                ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
 
1353
                                                stmt->lineno);
 
1354
                                ECPGraise_backend(stmt->lineno, results, stmt->connection->connection, stmt->compat);
 
1355
                                status = false;
 
1356
                                break;
 
1357
                }
 
1358
                if (clear_result)
 
1359
                        PQclear(results);
 
1360
        }
 
1361
 
 
1362
        /* check for asynchronous returns */
 
1363
        notify = PQnotifies(stmt->connection->connection);
 
1364
        if (notify)
 
1365
        {
 
1366
                ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
 
1367
                                stmt->lineno, notify->relname, notify->be_pid);
 
1368
                PQfreemem(notify);
 
1369
        }
 
1370
 
 
1371
        return status;
 
1372
}
 
1373
 
 
1374
bool
 
1375
ECPGdo(int lineno, int compat, int force_indicator, const char *connection_name, char *query,...)
 
1376
{
 
1377
        va_list         args;
 
1378
        struct statement *stmt;
 
1379
        struct connection *con = ECPGget_connection(connection_name);
 
1380
        bool            status;
 
1381
        char       *oldlocale;
 
1382
 
 
1383
        /* Make sure we do NOT honor the locale for numeric input/output */
 
1384
        /* since the database wants the standard decimal point */
 
1385
        oldlocale = strdup(setlocale(LC_NUMERIC, NULL));
 
1386
        setlocale(LC_NUMERIC, "C");
 
1387
 
 
1388
        if (!ECPGinit(con, connection_name, lineno))
 
1389
        {
 
1390
                setlocale(LC_NUMERIC, oldlocale);
 
1391
                ECPGfree(oldlocale);
 
1392
                return (false);
 
1393
        }
 
1394
 
 
1395
        /* construct statement in our own structure */
 
1396
        va_start(args, query);
 
1397
        if (create_statement(lineno, compat, force_indicator, con, &stmt, query, args) == false)
 
1398
        {
 
1399
                setlocale(LC_NUMERIC, oldlocale);
 
1400
                ECPGfree(oldlocale);
 
1401
                return (false);
 
1402
        }
 
1403
        va_end(args);
 
1404
 
 
1405
        /* are we connected? */
 
1406
        if (con == NULL || con->connection == NULL)
 
1407
        {
 
1408
                free_statement(stmt);
 
1409
                ECPGraise(lineno, ECPG_NOT_CONN, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, (con) ? con->name : "<empty>");
 
1410
                setlocale(LC_NUMERIC, oldlocale);
 
1411
                ECPGfree(oldlocale);
 
1412
                return false;
 
1413
        }
 
1414
 
 
1415
        /* initialize auto_mem struct */
 
1416
        ECPGclear_auto_mem();
 
1417
 
 
1418
        status = ECPGexecute(stmt);
 
1419
        free_statement(stmt);
 
1420
 
 
1421
        /* and reset locale value so our application is not affected */
 
1422
        setlocale(LC_NUMERIC, oldlocale);
 
1423
        ECPGfree(oldlocale);
 
1424
 
 
1425
        return (status);
 
1426
}
 
1427
 
 
1428
/* old descriptor interface */
 
1429
bool
 
1430
ECPGdo_descriptor(int line, const char *connection,
 
1431
                                  const char *descriptor, const char *query)
 
1432
{
 
1433
        return ECPGdo(line, ECPG_COMPAT_PGSQL, true, connection, (char *) query, ECPGt_EOIT,
 
1434
                                  ECPGt_descriptor, descriptor, 0L, 0L, 0L,
 
1435
                                  ECPGt_NO_INDICATOR, NULL, 0L, 0L, 0L, ECPGt_EORT);
 
1436
}