Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ecfd557

Browse files
committed
Fix incorrect results for numeric data passed through an ECPG SQLDA.
Numeric values with leading zeroes were incorrectly copied into a SQLDA (SQL Descriptor Area), leading to wrong results in ECPG programs. Report and patch by Daisuke Higuchi. Back-patch to all supported versions. Discussion: https://postgr.es/m/1803D792815FC24D871C00D17AE95905C71161@g01jpexmbkw24
1 parent 965a3d6 commit ecfd557

File tree

5 files changed

+380
-230
lines changed

5 files changed

+380
-230
lines changed

src/interfaces/ecpg/ecpglib/sqlda.c

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,12 @@ sqlda_common_total_size(const PGresult *res, int row, enum COMPAT_MODE compat, l
107107
case ECPGt_numeric:
108108

109109
/*
110-
* Let's align both the numeric struct and the digits array to
111-
* int Unfortunately we need to do double work here to compute
112-
* the size of the space needed for the numeric structure.
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.
113116
*/
114117
ecpg_sqlda_align_add_size(offset, sizeof(NumericDigit *), sizeof(numeric), &offset, &next_offset);
115118
if (!PQgetisnull(res, row, i))
@@ -120,8 +123,7 @@ sqlda_common_total_size(const PGresult *res, int row, enum COMPAT_MODE compat, l
120123
num = PGTYPESnumeric_from_asc(val, NULL);
121124
if (!num)
122125
break;
123-
if (num->ndigits)
124-
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->ndigits + 1, &offset, &next_offset);
126+
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
125127
PGTYPESnumeric_free(num);
126128
}
127129
break;
@@ -345,14 +347,11 @@ ecpg_set_compat_sqlda(int lineno, struct sqlda_compat **_sqlda, const PGresult *
345347

346348
memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
347349

348-
if (num->ndigits)
349-
{
350-
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->ndigits + 1, &offset, &next_offset);
351-
memcpy((char *) sqlda + offset, num->buf, num->ndigits + 1);
350+
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
351+
memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
352352

353-
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
354-
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
355-
}
353+
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
354+
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
356355

357356
PGTYPESnumeric_free(num);
358357

@@ -534,14 +533,11 @@ ecpg_set_native_sqlda(int lineno, struct sqlda_struct **_sqlda, const PGresult *
534533

535534
memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
536535

537-
if (num->ndigits)
538-
{
539-
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->ndigits + 1, &offset, &next_offset);
540-
memcpy((char *) sqlda + offset, num->buf, num->ndigits + 1);
536+
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
537+
memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
541538

542-
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
543-
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
544-
}
539+
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
540+
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
545541

546542
PGTYPESnumeric_free(num);
547543

src/interfaces/ecpg/test/expected/sql-sqlda.c

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -228,19 +228,19 @@ if (sqlca.sqlcode < 0) exit (1);}
228228

229229

230230
strcpy(msg, "insert");
231-
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into t1 values ( 1 , 'a' , 1.0 , 1 , 'a' , 1111111111111111111 ) , ( 2 , null , null , null , null , null ) , ( 4 , 'd' , 4.0 , 4 , 'd' , 4444444444444444444 )", ECPGt_EOIT, ECPGt_EORT);
232-
#line 97 "sqlda.pgc"
231+
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into t1 values ( 1 , 'a' , 1.0 , 1 , 'a' , 1111111111111111111 ) , ( 2 , null , null , null , null , null ) , ( 3 , 'c' , 0.0 , 3 , 'c' , 3333333333333333333 ) , ( 4 , 'd' , 4.0 , 4 , 'd' , 4444444444444444444 ) , ( 5 , 'e' , 0.001234 , 5 , 'e' , 5555555555555555555 )", ECPGt_EOIT, ECPGt_EORT);
232+
#line 99 "sqlda.pgc"
233233

234234
if (sqlca.sqlcode < 0) exit (1);}
235-
#line 97 "sqlda.pgc"
235+
#line 99 "sqlda.pgc"
236236

237237

238238
strcpy(msg, "commit");
239239
{ ECPGtrans(__LINE__, NULL, "commit");
240-
#line 100 "sqlda.pgc"
240+
#line 102 "sqlda.pgc"
241241

242242
if (sqlca.sqlcode < 0) exit (1);}
243-
#line 100 "sqlda.pgc"
243+
#line 102 "sqlda.pgc"
244244

245245

246246
/* SQLDA test for getting all records from a table */
@@ -249,29 +249,29 @@ if (sqlca.sqlcode < 0) exit (1);}
249249

250250
strcpy(msg, "prepare");
251251
{ ECPGprepare(__LINE__, NULL, 0, "st_id1", stmt1);
252-
#line 107 "sqlda.pgc"
252+
#line 109 "sqlda.pgc"
253253

254254
if (sqlca.sqlcode < 0) exit (1);}
255-
#line 107 "sqlda.pgc"
255+
#line 109 "sqlda.pgc"
256256

257257

258258
strcpy(msg, "declare");
259259
/* declare mycur1 cursor for $1 */
260-
#line 110 "sqlda.pgc"
260+
#line 112 "sqlda.pgc"
261261

262262

263263
strcpy(msg, "open");
264264
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare mycur1 cursor for $1",
265265
ECPGt_char_variable,(ECPGprepared_statement(NULL, "st_id1", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
266266
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
267-
#line 113 "sqlda.pgc"
267+
#line 115 "sqlda.pgc"
268268

269269
if (sqlca.sqlcode < 0) exit (1);}
270-
#line 113 "sqlda.pgc"
270+
#line 115 "sqlda.pgc"
271271

272272

273273
/* exec sql whenever not found break ; */
274-
#line 115 "sqlda.pgc"
274+
#line 117 "sqlda.pgc"
275275

276276

277277
rec = 0;
@@ -281,37 +281,37 @@ if (sqlca.sqlcode < 0) exit (1);}
281281
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 from mycur1", ECPGt_EOIT,
282282
ECPGt_sqlda, &outp_sqlda, 0L, 0L, 0L,
283283
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
284-
#line 121 "sqlda.pgc"
284+
#line 123 "sqlda.pgc"
285285

286286
if (sqlca.sqlcode == ECPG_NOT_FOUND) break;
287-
#line 121 "sqlda.pgc"
287+
#line 123 "sqlda.pgc"
288288

289289
if (sqlca.sqlcode < 0) exit (1);}
290-
#line 121 "sqlda.pgc"
290+
#line 123 "sqlda.pgc"
291291

292292

293293
printf("FETCH RECORD %d\n", ++rec);
294294
dump_sqlda(outp_sqlda);
295295
}
296296

297297
/* exec sql whenever not found continue ; */
298-
#line 127 "sqlda.pgc"
298+
#line 129 "sqlda.pgc"
299299

300300

301301
strcpy(msg, "close");
302302
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close mycur1", ECPGt_EOIT, ECPGt_EORT);
303-
#line 130 "sqlda.pgc"
303+
#line 132 "sqlda.pgc"
304304

305305
if (sqlca.sqlcode < 0) exit (1);}
306-
#line 130 "sqlda.pgc"
306+
#line 132 "sqlda.pgc"
307307

308308

309309
strcpy(msg, "deallocate");
310310
{ ECPGdeallocate(__LINE__, 0, NULL, "st_id1");
311-
#line 133 "sqlda.pgc"
311+
#line 135 "sqlda.pgc"
312312

313313
if (sqlca.sqlcode < 0) exit (1);}
314-
#line 133 "sqlda.pgc"
314+
#line 135 "sqlda.pgc"
315315

316316

317317
free(outp_sqlda);
@@ -322,35 +322,35 @@ if (sqlca.sqlcode < 0) exit (1);}
322322

323323
strcpy(msg, "prepare");
324324
{ ECPGprepare(__LINE__, NULL, 0, "st_id2", stmt1);
325-
#line 142 "sqlda.pgc"
325+
#line 144 "sqlda.pgc"
326326

327327
if (sqlca.sqlcode < 0) exit (1);}
328-
#line 142 "sqlda.pgc"
328+
#line 144 "sqlda.pgc"
329329

330330

331331
strcpy(msg, "declare");
332332
/* declare mycur2 cursor for $1 */
333-
#line 145 "sqlda.pgc"
333+
#line 147 "sqlda.pgc"
334334

335335

336336
strcpy(msg, "open");
337337
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare mycur2 cursor for $1",
338338
ECPGt_char_variable,(ECPGprepared_statement(NULL, "st_id2", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
339339
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
340-
#line 148 "sqlda.pgc"
340+
#line 150 "sqlda.pgc"
341341

342342
if (sqlca.sqlcode < 0) exit (1);}
343-
#line 148 "sqlda.pgc"
343+
#line 150 "sqlda.pgc"
344344

345345

346346
strcpy(msg, "fetch");
347347
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch all from mycur2", ECPGt_EOIT,
348348
ECPGt_sqlda, &outp_sqlda, 0L, 0L, 0L,
349349
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
350-
#line 151 "sqlda.pgc"
350+
#line 153 "sqlda.pgc"
351351

352352
if (sqlca.sqlcode < 0) exit (1);}
353-
#line 151 "sqlda.pgc"
353+
#line 153 "sqlda.pgc"
354354

355355

356356
outp_sqlda1 = outp_sqlda;
@@ -368,18 +368,18 @@ if (sqlca.sqlcode < 0) exit (1);}
368368

369369
strcpy(msg, "close");
370370
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close mycur2", ECPGt_EOIT, ECPGt_EORT);
371-
#line 167 "sqlda.pgc"
371+
#line 169 "sqlda.pgc"
372372

373373
if (sqlca.sqlcode < 0) exit (1);}
374-
#line 167 "sqlda.pgc"
374+
#line 169 "sqlda.pgc"
375375

376376

377377
strcpy(msg, "deallocate");
378378
{ ECPGdeallocate(__LINE__, 0, NULL, "st_id2");
379-
#line 170 "sqlda.pgc"
379+
#line 172 "sqlda.pgc"
380380

381381
if (sqlca.sqlcode < 0) exit (1);}
382-
#line 170 "sqlda.pgc"
382+
#line 172 "sqlda.pgc"
383383

384384

385385
/* SQLDA test for getting one record using an input descriptor */
@@ -403,10 +403,10 @@ if (sqlca.sqlcode < 0) exit (1);}
403403

404404
strcpy(msg, "prepare");
405405
{ ECPGprepare(__LINE__, NULL, 0, "st_id3", stmt2);
406-
#line 192 "sqlda.pgc"
406+
#line 194 "sqlda.pgc"
407407

408408
if (sqlca.sqlcode < 0) exit (1);}
409-
#line 192 "sqlda.pgc"
409+
#line 194 "sqlda.pgc"
410410

411411

412412
strcpy(msg, "execute");
@@ -415,20 +415,20 @@ if (sqlca.sqlcode < 0) exit (1);}
415415
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
416416
ECPGt_sqlda, &outp_sqlda, 0L, 0L, 0L,
417417
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
418-
#line 195 "sqlda.pgc"
418+
#line 197 "sqlda.pgc"
419419

420420
if (sqlca.sqlcode < 0) exit (1);}
421-
#line 195 "sqlda.pgc"
421+
#line 197 "sqlda.pgc"
422422

423423

424424
dump_sqlda(outp_sqlda);
425425

426426
strcpy(msg, "deallocate");
427427
{ ECPGdeallocate(__LINE__, 0, NULL, "st_id3");
428-
#line 200 "sqlda.pgc"
428+
#line 202 "sqlda.pgc"
429429

430430
if (sqlca.sqlcode < 0) exit (1);}
431-
#line 200 "sqlda.pgc"
431+
#line 202 "sqlda.pgc"
432432

433433

434434
free(inp_sqlda);
@@ -439,10 +439,10 @@ if (sqlca.sqlcode < 0) exit (1);}
439439
*/
440440

441441
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , "con2", 0);
442-
#line 209 "sqlda.pgc"
442+
#line 211 "sqlda.pgc"
443443

444444
if (sqlca.sqlcode < 0) exit (1);}
445-
#line 209 "sqlda.pgc"
445+
#line 211 "sqlda.pgc"
446446

447447

448448
/*
@@ -464,10 +464,10 @@ if (sqlca.sqlcode < 0) exit (1);}
464464

465465
strcpy(msg, "prepare");
466466
{ ECPGprepare(__LINE__, "con2", 0, "st_id4", stmt2);
467-
#line 229 "sqlda.pgc"
467+
#line 231 "sqlda.pgc"
468468

469469
if (sqlca.sqlcode < 0) exit (1);}
470-
#line 229 "sqlda.pgc"
470+
#line 231 "sqlda.pgc"
471471

472472

473473
strcpy(msg, "execute");
@@ -476,65 +476,65 @@ if (sqlca.sqlcode < 0) exit (1);}
476476
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
477477
ECPGt_sqlda, &outp_sqlda, 0L, 0L, 0L,
478478
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
479-
#line 232 "sqlda.pgc"
479+
#line 234 "sqlda.pgc"
480480

481481
if (sqlca.sqlcode < 0) exit (1);}
482-
#line 232 "sqlda.pgc"
482+
#line 234 "sqlda.pgc"
483483

484484

485485
dump_sqlda(outp_sqlda);
486486

487487
strcpy(msg, "commit");
488488
{ ECPGtrans(__LINE__, "con2", "commit");
489-
#line 237 "sqlda.pgc"
489+
#line 239 "sqlda.pgc"
490490

491491
if (sqlca.sqlcode < 0) exit (1);}
492-
#line 237 "sqlda.pgc"
492+
#line 239 "sqlda.pgc"
493493

494494

495495
strcpy(msg, "deallocate");
496496
{ ECPGdeallocate(__LINE__, 0, NULL, "st_id4");
497-
#line 240 "sqlda.pgc"
497+
#line 242 "sqlda.pgc"
498498

499499
if (sqlca.sqlcode < 0) exit (1);}
500-
#line 240 "sqlda.pgc"
500+
#line 242 "sqlda.pgc"
501501

502502

503503
free(inp_sqlda);
504504
free(outp_sqlda);
505505

506506
strcpy(msg, "disconnect");
507507
{ ECPGdisconnect(__LINE__, "con2");
508-
#line 246 "sqlda.pgc"
508+
#line 248 "sqlda.pgc"
509509

510510
if (sqlca.sqlcode < 0) exit (1);}
511-
#line 246 "sqlda.pgc"
511+
#line 248 "sqlda.pgc"
512512

513513

514514
/* End test */
515515

516516
strcpy(msg, "drop");
517517
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table t1", ECPGt_EOIT, ECPGt_EORT);
518-
#line 251 "sqlda.pgc"
518+
#line 253 "sqlda.pgc"
519519

520520
if (sqlca.sqlcode < 0) exit (1);}
521-
#line 251 "sqlda.pgc"
521+
#line 253 "sqlda.pgc"
522522

523523

524524
strcpy(msg, "commit");
525525
{ ECPGtrans(__LINE__, NULL, "commit");
526-
#line 254 "sqlda.pgc"
526+
#line 256 "sqlda.pgc"
527527

528528
if (sqlca.sqlcode < 0) exit (1);}
529-
#line 254 "sqlda.pgc"
529+
#line 256 "sqlda.pgc"
530530

531531

532532
strcpy(msg, "disconnect");
533533
{ ECPGdisconnect(__LINE__, "CURRENT");
534-
#line 257 "sqlda.pgc"
534+
#line 259 "sqlda.pgc"
535535

536536
if (sqlca.sqlcode < 0) exit (1);}
537-
#line 257 "sqlda.pgc"
537+
#line 259 "sqlda.pgc"
538538

539539

540540
return 0;

0 commit comments

Comments
 (0)