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