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