Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * SQLDA support routines
3 : : *
4 : : * The allocated memory area pointed by an sqlda pointer
5 : : * contains both the metadata and the data, so freeing up
6 : : * is a simple free(sqlda) as expected by the ESQL/C examples.
7 : : */
8 : :
9 : : #define POSTGRES_ECPG_INTERNAL
10 : : #include "postgres_fe.h"
11 : :
12 : : #include "catalog/pg_type_d.h"
13 : : #include "decimal.h"
14 : : #include "ecpg-pthread-win32.h"
15 : : #include "ecpgerrno.h"
16 : : #include "ecpglib.h"
17 : : #include "ecpglib_extern.h"
18 : : #include "ecpgtype.h"
19 : : #include "sqlca.h"
20 : : #include "sqlda-compat.h"
21 : : #include "sqlda-native.h"
22 : :
23 : : /*
24 : : * Compute the next variable's offset with
25 : : * the current variable's size and alignment.
26 : : *
27 : : *
28 : : * Returns:
29 : : * - the current variable's offset in *current
30 : : * - the next variable's offset in *next
31 : : */
32 : : static void
5213 meskes@postgresql.or 33 :CBC 296 : ecpg_sqlda_align_add_size(long offset, int alignment, int size, long *current, long *next)
34 : : {
35 [ + + ]: 296 : if (offset % alignment)
36 : 110 : offset += alignment - (offset % alignment);
37 [ + - ]: 296 : if (current)
38 : 296 : *current = offset;
39 : 296 : offset += size;
40 [ + + ]: 296 : if (next)
41 : 242 : *next = offset;
42 : 296 : }
43 : :
44 : : static long
45 : 22 : sqlda_compat_empty_size(const PGresult *res)
46 : : {
47 : : long offset;
48 : : int i;
5161 bruce@momjian.us 49 : 22 : int sqld = PQnfields(res);
50 : :
51 : : /* Initial size to store main structure and field structures */
5213 meskes@postgresql.or 52 : 22 : offset = sizeof(struct sqlda_compat) + sqld * sizeof(struct sqlvar_compat);
53 : :
54 : : /* Add space for field names */
55 [ + + ]: 114 : for (i = 0; i < sqld; i++)
56 : 92 : offset += strlen(PQfname(res, i)) + 1;
57 : :
58 : : /* Add padding to the first field value */
59 : 22 : ecpg_sqlda_align_add_size(offset, sizeof(int), 0, &offset, NULL);
60 : :
61 : 22 : return offset;
62 : : }
63 : :
64 : : static long
65 : 21 : sqlda_common_total_size(const PGresult *res, int row, enum COMPAT_MODE compat, long offset)
66 : : {
5161 bruce@momjian.us 67 : 21 : int sqld = PQnfields(res);
68 : : int i;
69 : : long next_offset;
70 : :
71 : : /* Add space for the field values */
5213 meskes@postgresql.or 72 [ + + ]: 135 : for (i = 0; i < sqld; i++)
73 : : {
74 : 114 : enum ECPGttype type = sqlda_dynamic_type(PQftype(res, i), compat);
75 : :
76 [ - + + - : 114 : switch (type)
- - + + +
- - - + ]
77 : : {
5213 meskes@postgresql.or 78 :UBC 0 : case ECPGt_short:
79 : : case ECPGt_unsigned_short:
80 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(short), sizeof(short), &offset, &next_offset);
81 : 0 : break;
5213 meskes@postgresql.or 82 :CBC 20 : case ECPGt_int:
83 : : case ECPGt_unsigned_int:
84 : 20 : ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(int), &offset, &next_offset);
85 : 20 : break;
86 : 12 : case ECPGt_long:
87 : : case ECPGt_unsigned_long:
88 : 12 : ecpg_sqlda_align_add_size(offset, sizeof(long), sizeof(long), &offset, &next_offset);
89 : 12 : break;
5213 meskes@postgresql.or 90 :UBC 0 : case ECPGt_long_long:
91 : : case ECPGt_unsigned_long_long:
92 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(long long), sizeof(long long), &offset, &next_offset);
93 : 0 : break;
94 : 0 : case ECPGt_bool:
95 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(bool), sizeof(bool), &offset, &next_offset);
96 : 0 : break;
97 : 0 : case ECPGt_float:
98 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(float), sizeof(float), &offset, &next_offset);
99 : 0 : break;
5213 meskes@postgresql.or 100 :CBC 20 : case ECPGt_double:
101 : 20 : ecpg_sqlda_align_add_size(offset, sizeof(double), sizeof(double), &offset, &next_offset);
102 : 20 : break;
103 : 8 : case ECPGt_decimal:
104 : 8 : ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(decimal), &offset, &next_offset);
105 : 8 : break;
106 : 13 : case ECPGt_numeric:
107 : :
108 : : /*
109 : : * We align the numeric struct to allow it to store a pointer,
110 : : * while the digits array is aligned to int (which seems like
111 : : * overkill, but let's keep compatibility here).
112 : : *
113 : : * Unfortunately we need to deconstruct the value twice to
114 : : * find out the digits array's size and then later fill it.
115 : : */
4516 116 : 13 : ecpg_sqlda_align_add_size(offset, sizeof(NumericDigit *), sizeof(numeric), &offset, &next_offset);
5213 117 [ + + ]: 13 : if (!PQgetisnull(res, row, i))
118 : : {
119 : 11 : char *val = PQgetvalue(res, row, i);
120 : : numeric *num;
121 : :
122 : 11 : num = PGTYPESnumeric_from_asc(val, NULL);
123 [ - + ]: 11 : if (!num)
5213 meskes@postgresql.or 124 :UBC 0 : break;
1978 tgl@sss.pgh.pa.us 125 [ + + ]:CBC 11 : if (num->buf)
126 : 7 : ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
5213 meskes@postgresql.or 127 : 11 : PGTYPESnumeric_free(num);
128 : : }
129 : 13 : break;
5213 meskes@postgresql.or 130 :UBC 0 : case ECPGt_date:
4536 131 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(date), sizeof(date), &offset, &next_offset);
5213 132 : 0 : break;
133 : 0 : case ECPGt_timestamp:
4532 134 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(timestamp), &offset, &next_offset);
5213 135 : 0 : break;
136 : 0 : case ECPGt_interval:
4532 137 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(interval), &offset, &next_offset);
5213 138 : 0 : break;
5213 meskes@postgresql.or 139 :CBC 41 : case ECPGt_char:
140 : : case ECPGt_unsigned_char:
141 : : case ECPGt_string:
142 : : default:
143 : : {
5161 bruce@momjian.us 144 : 41 : long datalen = strlen(PQgetvalue(res, row, i)) + 1;
145 : :
146 : 41 : ecpg_sqlda_align_add_size(offset, sizeof(int), datalen, &offset, &next_offset);
147 : 41 : break;
148 : : }
149 : : }
5213 meskes@postgresql.or 150 : 114 : offset = next_offset;
151 : : }
152 : 21 : return offset;
153 : : }
154 : :
155 : :
156 : : static long
157 : 14 : sqlda_compat_total_size(const PGresult *res, int row, enum COMPAT_MODE compat)
158 : : {
159 : : long offset;
160 : :
161 : 14 : offset = sqlda_compat_empty_size(res);
162 : :
163 [ + + ]: 14 : if (row < 0)
164 : 6 : return offset;
165 : :
166 : 8 : offset = sqlda_common_total_size(res, row, compat, offset);
167 : 8 : return offset;
168 : : }
169 : :
170 : : static long
171 : 32 : sqlda_native_empty_size(const PGresult *res)
172 : : {
173 : : long offset;
5161 bruce@momjian.us 174 : 32 : int sqld = PQnfields(res);
175 : :
176 : : /* Initial size to store main structure and field structures */
5213 meskes@postgresql.or 177 : 32 : offset = sizeof(struct sqlda_struct) + (sqld - 1) * sizeof(struct sqlvar_struct);
178 : :
179 : : /* Add padding to the first field value */
180 : 32 : ecpg_sqlda_align_add_size(offset, sizeof(int), 0, &offset, NULL);
181 : :
182 : 32 : return offset;
183 : : }
184 : :
185 : : static long
186 : 19 : sqlda_native_total_size(const PGresult *res, int row, enum COMPAT_MODE compat)
187 : : {
188 : : long offset;
189 : :
190 : 19 : offset = sqlda_native_empty_size(res);
191 : :
192 [ + + ]: 19 : if (row < 0)
193 : 6 : return offset;
194 : :
195 : 13 : offset = sqlda_common_total_size(res, row, compat, offset);
196 : 13 : return offset;
197 : : }
198 : :
199 : : /*
200 : : * Build "struct sqlda_compat" (metadata only) from PGresult
201 : : * leaving enough space for the field values in
202 : : * the given row number
203 : : */
204 : : struct sqlda_compat *
205 : 14 : ecpg_build_compat_sqlda(int line, PGresult *res, int row, enum COMPAT_MODE compat)
206 : : {
207 : : struct sqlda_compat *sqlda;
208 : : struct sqlvar_compat *sqlvar;
209 : : char *fname;
210 : : long size;
211 : : int sqld;
212 : : int i;
213 : :
214 : 14 : size = sqlda_compat_total_size(res, row, compat);
5161 bruce@momjian.us 215 : 14 : sqlda = (struct sqlda_compat *) ecpg_alloc(size, line);
5213 meskes@postgresql.or 216 [ - + ]: 14 : if (!sqlda)
5213 meskes@postgresql.or 217 :UBC 0 : return NULL;
218 : :
5213 meskes@postgresql.or 219 :CBC 14 : memset(sqlda, 0, size);
5161 bruce@momjian.us 220 : 14 : sqlvar = (struct sqlvar_compat *) (sqlda + 1);
5213 meskes@postgresql.or 221 : 14 : sqld = PQnfields(res);
5161 bruce@momjian.us 222 : 14 : fname = (char *) (sqlvar + sqld);
223 : :
5213 meskes@postgresql.or 224 : 14 : sqlda->sqld = sqld;
5212 225 : 14 : ecpg_log("ecpg_build_compat_sqlda on line %d sqld = %d\n", line, sqld);
5161 bruce@momjian.us 226 : 14 : sqlda->desc_occ = size; /* cheat here, keep the full allocated size */
5213 meskes@postgresql.or 227 : 14 : sqlda->sqlvar = sqlvar;
228 : :
229 [ + + ]: 66 : for (i = 0; i < sqlda->sqld; i++)
230 : : {
231 : 52 : sqlda->sqlvar[i].sqltype = sqlda_dynamic_type(PQftype(res, i), compat);
232 : 52 : strcpy(fname, PQfname(res, i));
233 : 52 : sqlda->sqlvar[i].sqlname = fname;
234 : 52 : fname += strlen(sqlda->sqlvar[i].sqlname) + 1;
235 : :
236 : : /*
237 : : * this is reserved for future use, so we leave it empty for the time
238 : : * being
239 : : */
240 : : /* sqlda->sqlvar[i].sqlformat = (char *) (long) PQfformat(res, i); */
241 : 52 : sqlda->sqlvar[i].sqlxid = PQftype(res, i);
242 : 52 : sqlda->sqlvar[i].sqltypelen = PQfsize(res, i);
243 : : }
244 : :
245 : 14 : return sqlda;
246 : : }
247 : :
248 : : /*
249 : : * Sets values from PGresult.
250 : : */
251 : : static int16 value_is_null = -1;
252 : : static int16 value_is_not_null = 0;
253 : :
254 : : void
2489 tgl@sss.pgh.pa.us 255 : 8 : ecpg_set_compat_sqlda(int lineno, struct sqlda_compat **_sqlda, const PGresult *res, int row, enum COMPAT_MODE compat)
256 : : {
5213 meskes@postgresql.or 257 : 8 : struct sqlda_compat *sqlda = (*_sqlda);
258 : : int i;
259 : : long offset,
260 : : next_offset;
261 : :
262 [ - + ]: 8 : if (row < 0)
5213 meskes@postgresql.or 263 :UBC 0 : return;
264 : :
265 : : /* Offset for the first field value */
5213 meskes@postgresql.or 266 :CBC 8 : offset = sqlda_compat_empty_size(res);
267 : :
268 : : /*
269 : : * Set sqlvar[i]->sqldata pointers and convert values to correct format
270 : : */
271 [ + + ]: 48 : for (i = 0; i < sqlda->sqld; i++)
272 : : {
273 : : int isnull;
274 : : int datalen;
5161 bruce@momjian.us 275 : 40 : bool set_data = true;
276 : :
5213 meskes@postgresql.or 277 [ - + - - : 40 : switch (sqlda->sqlvar[i].sqltype)
- - + + -
- - - + ]
278 : : {
5213 meskes@postgresql.or 279 :UBC 0 : case ECPGt_short:
280 : : case ECPGt_unsigned_short:
281 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(short), sizeof(short), &offset, &next_offset);
5161 bruce@momjian.us 282 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 283 : 0 : sqlda->sqlvar[i].sqllen = sizeof(short);
284 : 0 : break;
5213 meskes@postgresql.or 285 :CBC 8 : case ECPGt_int:
286 : : case ECPGt_unsigned_int:
287 : 8 : ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(int), &offset, &next_offset);
5161 bruce@momjian.us 288 : 8 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 289 : 8 : sqlda->sqlvar[i].sqllen = sizeof(int);
290 : 8 : break;
5213 meskes@postgresql.or 291 :UBC 0 : case ECPGt_long:
292 : : case ECPGt_unsigned_long:
293 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(long), sizeof(long), &offset, &next_offset);
5161 bruce@momjian.us 294 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 295 : 0 : sqlda->sqlvar[i].sqllen = sizeof(long);
296 : 0 : break;
297 : 0 : case ECPGt_long_long:
298 : : case ECPGt_unsigned_long_long:
299 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(long long), sizeof(long long), &offset, &next_offset);
5161 bruce@momjian.us 300 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 301 : 0 : sqlda->sqlvar[i].sqllen = sizeof(long long);
302 : 0 : break;
303 : 0 : case ECPGt_bool:
304 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(bool), sizeof(bool), &offset, &next_offset);
5161 bruce@momjian.us 305 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 306 : 0 : sqlda->sqlvar[i].sqllen = sizeof(bool);
307 : 0 : break;
308 : 0 : case ECPGt_float:
309 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(float), sizeof(float), &offset, &next_offset);
5161 bruce@momjian.us 310 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 311 : 0 : sqlda->sqlvar[i].sqllen = sizeof(float);
312 : 0 : break;
5213 meskes@postgresql.or 313 :CBC 8 : case ECPGt_double:
314 : 8 : ecpg_sqlda_align_add_size(offset, sizeof(double), sizeof(double), &offset, &next_offset);
5161 bruce@momjian.us 315 : 8 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 316 : 8 : sqlda->sqlvar[i].sqllen = sizeof(double);
317 : 8 : break;
318 : 8 : case ECPGt_decimal:
319 : 8 : ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(decimal), &offset, &next_offset);
5161 bruce@momjian.us 320 : 8 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 321 : 8 : sqlda->sqlvar[i].sqllen = sizeof(decimal);
322 : 8 : break;
5213 meskes@postgresql.or 323 :UBC 0 : case ECPGt_numeric:
324 : : {
325 : : numeric *num;
326 : : char *val;
327 : :
5161 bruce@momjian.us 328 : 0 : set_data = false;
329 : :
4516 meskes@postgresql.or 330 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(NumericDigit *), sizeof(numeric), &offset, &next_offset);
5161 bruce@momjian.us 331 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
332 : 0 : sqlda->sqlvar[i].sqllen = sizeof(numeric);
333 : :
334 [ # # ]: 0 : if (PQgetisnull(res, row, i))
335 : : {
336 : 0 : ECPGset_noind_null(ECPGt_numeric, sqlda->sqlvar[i].sqldata);
337 : 0 : break;
338 : : }
339 : :
340 : 0 : val = PQgetvalue(res, row, i);
341 : 0 : num = PGTYPESnumeric_from_asc(val, NULL);
342 [ # # ]: 0 : if (!num)
343 : : {
344 : 0 : ECPGset_noind_null(ECPGt_numeric, sqlda->sqlvar[i].sqldata);
345 : 0 : break;
346 : : }
347 : :
348 : 0 : memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
349 : :
1978 tgl@sss.pgh.pa.us 350 [ # # ]: 0 : if (num->buf)
351 : : {
352 : 0 : ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
353 : 0 : memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
354 : :
355 : 0 : ((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
356 : 0 : ((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
357 : : }
358 : :
5161 bruce@momjian.us 359 : 0 : PGTYPESnumeric_free(num);
360 : :
361 : 0 : break;
362 : : }
5213 meskes@postgresql.or 363 : 0 : case ECPGt_date:
364 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(date), sizeof(date), &offset, &next_offset);
5161 bruce@momjian.us 365 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 366 : 0 : sqlda->sqlvar[i].sqllen = sizeof(date);
367 : 0 : break;
368 : 0 : case ECPGt_timestamp:
4532 369 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(timestamp), &offset, &next_offset);
5161 bruce@momjian.us 370 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 371 : 0 : sqlda->sqlvar[i].sqllen = sizeof(timestamp);
372 : 0 : break;
373 : 0 : case ECPGt_interval:
5212 374 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(interval), &offset, &next_offset);
5161 bruce@momjian.us 375 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 376 : 0 : sqlda->sqlvar[i].sqllen = sizeof(interval);
377 : 0 : break;
5213 meskes@postgresql.or 378 :CBC 16 : case ECPGt_char:
379 : : case ECPGt_unsigned_char:
380 : : case ECPGt_string:
381 : : default:
382 : 16 : datalen = strlen(PQgetvalue(res, row, i)) + 1;
383 : 16 : ecpg_sqlda_align_add_size(offset, sizeof(int), datalen, &offset, &next_offset);
5161 bruce@momjian.us 384 : 16 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 385 : 16 : sqlda->sqlvar[i].sqllen = datalen;
386 [ - + ]: 16 : if (datalen > 32768)
5213 meskes@postgresql.or 387 :UBC 0 : sqlda->sqlvar[i].sqlilongdata = sqlda->sqlvar[i].sqldata;
5213 meskes@postgresql.or 388 :CBC 16 : break;
389 : : }
390 : :
391 : 40 : isnull = PQgetisnull(res, row, i);
5212 392 [ + + ]: 40 : ecpg_log("ecpg_set_compat_sqlda on line %d row %d col %d %s\n", lineno, row, i, isnull ? "IS NULL" : "IS NOT NULL");
5213 393 [ + + ]: 40 : sqlda->sqlvar[i].sqlind = isnull ? &value_is_null : &value_is_not_null;
394 : 40 : sqlda->sqlvar[i].sqlitype = ECPGt_short;
395 : 40 : sqlda->sqlvar[i].sqlilen = sizeof(short);
396 [ + + ]: 40 : if (!isnull)
397 : : {
398 [ + - ]: 32 : if (set_data)
399 : 32 : ecpg_get_data(res, row, i, lineno,
5161 bruce@momjian.us 400 : 32 : sqlda->sqlvar[i].sqltype, ECPGt_NO_INDICATOR,
401 : 32 : sqlda->sqlvar[i].sqldata, NULL, 0, 0, 0,
402 : : ECPG_ARRAY_NONE, compat, false);
403 : : }
404 : : else
5213 meskes@postgresql.or 405 : 8 : ECPGset_noind_null(sqlda->sqlvar[i].sqltype, sqlda->sqlvar[i].sqldata);
406 : :
407 : 40 : offset = next_offset;
408 : : }
409 : : }
410 : :
411 : : struct sqlda_struct *
412 : 19 : ecpg_build_native_sqlda(int line, PGresult *res, int row, enum COMPAT_MODE compat)
413 : : {
414 : : struct sqlda_struct *sqlda;
415 : : long size;
416 : : int i;
417 : :
418 : 19 : size = sqlda_native_total_size(res, row, compat);
5161 bruce@momjian.us 419 : 19 : sqlda = (struct sqlda_struct *) ecpg_alloc(size, line);
5213 meskes@postgresql.or 420 [ - + ]: 19 : if (!sqlda)
5213 meskes@postgresql.or 421 :UBC 0 : return NULL;
422 : :
5213 meskes@postgresql.or 423 :CBC 19 : memset(sqlda, 0, size);
424 : :
425 : 19 : sprintf(sqlda->sqldaid, "SQLDA ");
426 : 19 : sqlda->sqld = sqlda->sqln = PQnfields(res);
5212 427 : 19 : ecpg_log("ecpg_build_native_sqlda on line %d sqld = %d\n", line, sqlda->sqld);
5213 428 : 19 : sqlda->sqldabc = sizeof(struct sqlda_struct) + (sqlda->sqld - 1) * sizeof(struct sqlvar_struct);
429 : :
430 [ + + ]: 105 : for (i = 0; i < sqlda->sqld; i++)
431 : : {
432 : : char *fname;
433 : :
434 : 86 : sqlda->sqlvar[i].sqltype = sqlda_dynamic_type(PQftype(res, i), compat);
435 : 86 : fname = PQfname(res, i);
436 : 86 : sqlda->sqlvar[i].sqlname.length = strlen(fname);
437 : 86 : strcpy(sqlda->sqlvar[i].sqlname.data, fname);
438 : : }
439 : :
440 : 19 : return sqlda;
441 : : }
442 : :
443 : : void
2489 tgl@sss.pgh.pa.us 444 : 13 : ecpg_set_native_sqlda(int lineno, struct sqlda_struct **_sqlda, const PGresult *res, int row, enum COMPAT_MODE compat)
445 : : {
5213 meskes@postgresql.or 446 : 13 : struct sqlda_struct *sqlda = (*_sqlda);
447 : : int i;
448 : : long offset,
449 : : next_offset;
450 : :
451 [ - + ]: 13 : if (row < 0)
5213 meskes@postgresql.or 452 :UBC 0 : return;
453 : :
454 : : /* Offset for the first field value */
5213 meskes@postgresql.or 455 :CBC 13 : offset = sqlda_native_empty_size(res);
456 : :
457 : : /*
458 : : * Set sqlvar[i]->sqldata pointers and convert values to correct format
459 : : */
460 [ + + ]: 87 : for (i = 0; i < sqlda->sqld; i++)
461 : : {
462 : : int isnull;
463 : : int datalen;
5161 bruce@momjian.us 464 : 74 : bool set_data = true;
465 : :
5213 meskes@postgresql.or 466 [ - + + - : 74 : switch (sqlda->sqlvar[i].sqltype)
- - + - +
- - - + ]
467 : : {
5213 meskes@postgresql.or 468 :UBC 0 : case ECPGt_short:
469 : : case ECPGt_unsigned_short:
470 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(short), sizeof(short), &offset, &next_offset);
5161 bruce@momjian.us 471 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 472 : 0 : sqlda->sqlvar[i].sqllen = sizeof(short);
473 : 0 : break;
5213 meskes@postgresql.or 474 :CBC 12 : case ECPGt_int:
475 : : case ECPGt_unsigned_int:
476 : 12 : ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(int), &offset, &next_offset);
5161 bruce@momjian.us 477 : 12 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 478 : 12 : sqlda->sqlvar[i].sqllen = sizeof(int);
479 : 12 : break;
480 : 12 : case ECPGt_long:
481 : : case ECPGt_unsigned_long:
482 : 12 : ecpg_sqlda_align_add_size(offset, sizeof(long), sizeof(long), &offset, &next_offset);
5161 bruce@momjian.us 483 : 12 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 484 : 12 : sqlda->sqlvar[i].sqllen = sizeof(long);
485 : 12 : break;
5213 meskes@postgresql.or 486 :UBC 0 : case ECPGt_long_long:
487 : : case ECPGt_unsigned_long_long:
488 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(long long), sizeof(long long), &offset, &next_offset);
5161 bruce@momjian.us 489 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 490 : 0 : sqlda->sqlvar[i].sqllen = sizeof(long long);
491 : 0 : break;
492 : 0 : case ECPGt_bool:
493 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(bool), sizeof(bool), &offset, &next_offset);
5161 bruce@momjian.us 494 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 495 : 0 : sqlda->sqlvar[i].sqllen = sizeof(bool);
496 : 0 : break;
497 : 0 : case ECPGt_float:
498 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(float), sizeof(float), &offset, &next_offset);
5161 bruce@momjian.us 499 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 500 : 0 : sqlda->sqlvar[i].sqllen = sizeof(float);
501 : 0 : break;
5213 meskes@postgresql.or 502 :CBC 12 : case ECPGt_double:
503 : 12 : ecpg_sqlda_align_add_size(offset, sizeof(double), sizeof(double), &offset, &next_offset);
5161 bruce@momjian.us 504 : 12 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 505 : 12 : sqlda->sqlvar[i].sqllen = sizeof(double);
506 : 12 : break;
5213 meskes@postgresql.or 507 :UBC 0 : case ECPGt_decimal:
508 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(decimal), &offset, &next_offset);
5161 bruce@momjian.us 509 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 510 : 0 : sqlda->sqlvar[i].sqllen = sizeof(decimal);
511 : 0 : break;
5213 meskes@postgresql.or 512 :CBC 13 : case ECPGt_numeric:
513 : : {
514 : : numeric *num;
515 : : char *val;
516 : :
5161 bruce@momjian.us 517 : 13 : set_data = false;
518 : :
4516 meskes@postgresql.or 519 : 13 : ecpg_sqlda_align_add_size(offset, sizeof(NumericDigit *), sizeof(numeric), &offset, &next_offset);
5161 bruce@momjian.us 520 : 13 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
521 : 13 : sqlda->sqlvar[i].sqllen = sizeof(numeric);
522 : :
523 [ + + ]: 13 : if (PQgetisnull(res, row, i))
524 : : {
525 : 2 : ECPGset_noind_null(ECPGt_numeric, sqlda->sqlvar[i].sqldata);
526 : 2 : break;
527 : : }
528 : :
529 : 11 : val = PQgetvalue(res, row, i);
530 : 11 : num = PGTYPESnumeric_from_asc(val, NULL);
531 [ - + ]: 11 : if (!num)
532 : : {
5161 bruce@momjian.us 533 :UBC 0 : ECPGset_noind_null(ECPGt_numeric, sqlda->sqlvar[i].sqldata);
534 : 0 : break;
535 : : }
536 : :
5161 bruce@momjian.us 537 :CBC 11 : memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
538 : :
1978 tgl@sss.pgh.pa.us 539 [ + + ]: 11 : if (num->buf)
540 : : {
541 : 7 : ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
542 : 7 : memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
543 : :
544 : 7 : ((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
545 : 7 : ((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
546 : : }
547 : :
5161 bruce@momjian.us 548 : 11 : PGTYPESnumeric_free(num);
549 : :
550 : 11 : break;
551 : : }
5213 meskes@postgresql.or 552 :UBC 0 : case ECPGt_date:
553 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(date), sizeof(date), &offset, &next_offset);
5161 bruce@momjian.us 554 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 555 : 0 : sqlda->sqlvar[i].sqllen = sizeof(date);
556 : 0 : break;
557 : 0 : case ECPGt_timestamp:
4532 558 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(timestamp), &offset, &next_offset);
5161 bruce@momjian.us 559 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 560 : 0 : sqlda->sqlvar[i].sqllen = sizeof(timestamp);
561 : 0 : break;
562 : 0 : case ECPGt_interval:
5212 563 : 0 : ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(interval), &offset, &next_offset);
5161 bruce@momjian.us 564 : 0 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 565 : 0 : sqlda->sqlvar[i].sqllen = sizeof(interval);
566 : 0 : break;
5213 meskes@postgresql.or 567 :CBC 25 : case ECPGt_char:
568 : : case ECPGt_unsigned_char:
569 : : case ECPGt_string:
570 : : default:
571 : 25 : datalen = strlen(PQgetvalue(res, row, i)) + 1;
572 : 25 : ecpg_sqlda_align_add_size(offset, sizeof(int), datalen, &offset, &next_offset);
5161 bruce@momjian.us 573 : 25 : sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
5213 meskes@postgresql.or 574 : 25 : sqlda->sqlvar[i].sqllen = datalen;
575 : 25 : break;
576 : : }
577 : :
578 : 74 : isnull = PQgetisnull(res, row, i);
5212 579 [ + + ]: 74 : ecpg_log("ecpg_set_native_sqlda on line %d row %d col %d %s\n", lineno, row, i, isnull ? "IS NULL" : "IS NOT NULL");
5213 580 [ + + ]: 74 : sqlda->sqlvar[i].sqlind = isnull ? &value_is_null : &value_is_not_null;
581 [ + + ]: 74 : if (!isnull)
582 : : {
583 [ + + ]: 64 : if (set_data)
584 : 53 : ecpg_get_data(res, row, i, lineno,
5161 bruce@momjian.us 585 : 53 : sqlda->sqlvar[i].sqltype, ECPGt_NO_INDICATOR,
586 : : sqlda->sqlvar[i].sqldata, NULL, 0, 0, 0,
587 : : ECPG_ARRAY_NONE, compat, false);
588 : : }
589 : :
5213 meskes@postgresql.or 590 : 74 : offset = next_offset;
591 : : }
592 : : }
|