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

+15-19
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

+54-54
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)