Skip to content

Commit 9be9ac4

Browse files
author
Michael Meskes
committed
Fixed array handling in ecpg.
When ecpg was rewritten to the new protocol version not all variable types were corrected. This patch rewrites the code for these types to fix that. It also fixes the documentation to correctly tell the status of array handling.
1 parent 2593c70 commit 9be9ac4

File tree

3 files changed

+165
-174
lines changed

3 files changed

+165
-174
lines changed

doc/src/sgml/ecpg.sgml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,10 +1375,13 @@ EXEC SQL END DECLARE SECTION;
13751375
<title>Arrays</title>
13761376

13771377
<para>
1378-
SQL-level arrays are not directly supported in ECPG. It is not
1379-
possible to simply map an SQL array into a C array host variable.
1380-
This will result in undefined behavior. Some workarounds exist,
1381-
however.
1378+
Multi-dimensional SQL-level arrays are not directly supported in ECPG.
1379+
One-dimensional SQL-level arrays can be mapped into C array host
1380+
variables and vice-versa. However, when creating a statement ecpg does
1381+
not know the types of the columns, so that it cannot check if a C array
1382+
is input into a corresponding SQL-level array. When processing the
1383+
output of a SQL statement, ecpg has the necessary information and thus
1384+
checks if both are arrays.
13821385
</para>
13831386

13841387
<para>

src/interfaces/ecpg/ecpglib/data.c

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
291291
date ddres;
292292
timestamp tres;
293293
interval *ires;
294+
char *endptr, endchar;
294295

295296
case ECPGt_short:
296297
case ECPGt_int:
@@ -564,10 +565,11 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
564565

565566
case ECPGt_decimal:
566567
case ECPGt_numeric:
567-
if (isarray && *pval == '"')
568-
nres = PGTYPESnumeric_from_asc(pval + 1, &scan_length);
569-
else
570-
nres = PGTYPESnumeric_from_asc(pval, &scan_length);
568+
for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
569+
endchar = *endptr;
570+
*endptr = '\0';
571+
nres = PGTYPESnumeric_from_asc(pval, &scan_length);
572+
*endptr = endchar;
571573

572574
/* did we get an error? */
573575
if (nres == NULL)
@@ -600,10 +602,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
600602
}
601603
else
602604
{
603-
if (isarray && *scan_length == '"')
604-
scan_length++;
605-
606-
if (garbage_left(isarray, scan_length, compat))
605+
if (!isarray && garbage_left(isarray, scan_length, compat))
607606
{
608607
free(nres);
609608
ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
@@ -622,10 +621,14 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
622621
break;
623622

624623
case ECPGt_interval:
625-
if (isarray && *pval == '"')
626-
ires = PGTYPESinterval_from_asc(pval + 1, &scan_length);
627-
else
628-
ires = PGTYPESinterval_from_asc(pval, &scan_length);
624+
if (*pval == '"')
625+
pval++;
626+
627+
for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
628+
endchar = *endptr;
629+
*endptr = '\0';
630+
ires = PGTYPESinterval_from_asc(pval, &scan_length);
631+
*endptr = endchar;
629632

630633
/* did we get an error? */
631634
if (ires == NULL)
@@ -654,10 +657,10 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
654657
}
655658
else
656659
{
657-
if (isarray && *scan_length == '"')
660+
if (*scan_length == '"')
658661
scan_length++;
659662

660-
if (garbage_left(isarray, scan_length, compat))
663+
if (!isarray && garbage_left(isarray, scan_length, compat))
661664
{
662665
free(ires);
663666
ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
@@ -672,10 +675,14 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
672675
break;
673676

674677
case ECPGt_date:
675-
if (isarray && *pval == '"')
676-
ddres = PGTYPESdate_from_asc(pval + 1, &scan_length);
677-
else
678-
ddres = PGTYPESdate_from_asc(pval, &scan_length);
678+
if (*pval == '"')
679+
pval++;
680+
681+
for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
682+
endchar = *endptr;
683+
*endptr = '\0';
684+
ddres = PGTYPESdate_from_asc(pval, &scan_length);
685+
*endptr = endchar;
679686

680687
/* did we get an error? */
681688
if (errno != 0)
@@ -700,10 +707,10 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
700707
}
701708
else
702709
{
703-
if (isarray && *scan_length == '"')
710+
if (*scan_length == '"')
704711
scan_length++;
705712

706-
if (garbage_left(isarray, scan_length, compat))
713+
if (!isarray && garbage_left(isarray, scan_length, compat))
707714
{
708715
ecpg_raise(lineno, ECPG_DATE_FORMAT,
709716
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
@@ -716,10 +723,14 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
716723
break;
717724

718725
case ECPGt_timestamp:
719-
if (isarray && *pval == '"')
720-
tres = PGTYPEStimestamp_from_asc(pval + 1, &scan_length);
721-
else
722-
tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
726+
if (*pval == '"')
727+
pval++;
728+
729+
for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
730+
endchar = *endptr;
731+
*endptr = '\0';
732+
tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
733+
*endptr = endchar;
723734

724735
/* did we get an error? */
725736
if (errno != 0)
@@ -744,10 +755,10 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
744755
}
745756
else
746757
{
747-
if (isarray && *scan_length == '"')
758+
if (*scan_length == '"')
748759
scan_length++;
749760

750-
if (garbage_left(isarray, scan_length, compat))
761+
if (!isarray && garbage_left(isarray, scan_length, compat))
751762
{
752763
ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
753764
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);

0 commit comments

Comments
 (0)