Commit 06c72344 authored by Tom Lane's avatar Tom Lane

Second try at fixing numeric data passed through an ECPG SQLDA.

In commit ecfd5579, I removed sqlda.c's checks for ndigits != 0 on the
grounds that we should duplicate the state of the numeric value's digit
buffer even when all the digits are zeroes.  However, that still isn't
quite right, because another possible state of the digit buffer is
buf == digits == NULL (this occurs for a NaN).  As the code now stands,
it'll invoke memcpy with a NULL source address and zero bytecount,
which we know a few platforms crash on.  Hence, reinstate the no-copy
short-circuit, but make it test specifically for buf != NULL rather than
some other condition.  In hindsight, the ndigits test (added by commit
f2ae9f9c) was almost certainly meant to fix the NaN case not the
all-zeroes case as the associated thread alleged.

As before, back-patch to all supported versions.

Discussion: https://postgr.es/m/1803D792815FC24D871C00D17AE95905C71161@g01jpexmbkw24
parent 1b5d797c
...@@ -123,6 +123,7 @@ sqlda_common_total_size(const PGresult *res, int row, enum COMPAT_MODE compat, l ...@@ -123,6 +123,7 @@ sqlda_common_total_size(const PGresult *res, int row, enum COMPAT_MODE compat, l
num = PGTYPESnumeric_from_asc(val, NULL); num = PGTYPESnumeric_from_asc(val, NULL);
if (!num) if (!num)
break; break;
if (num->buf)
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset); ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
PGTYPESnumeric_free(num); PGTYPESnumeric_free(num);
} }
...@@ -347,11 +348,14 @@ ecpg_set_compat_sqlda(int lineno, struct sqlda_compat **_sqlda, const PGresult * ...@@ -347,11 +348,14 @@ ecpg_set_compat_sqlda(int lineno, struct sqlda_compat **_sqlda, const PGresult *
memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric)); memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
if (num->buf)
{
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset); ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits); memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset; ((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf); ((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
}
PGTYPESnumeric_free(num); PGTYPESnumeric_free(num);
...@@ -533,11 +537,14 @@ ecpg_set_native_sqlda(int lineno, struct sqlda_struct **_sqlda, const PGresult * ...@@ -533,11 +537,14 @@ ecpg_set_native_sqlda(int lineno, struct sqlda_struct **_sqlda, const PGresult *
memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric)); memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
if (num->buf)
{
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset); ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits); memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset; ((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf); ((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
}
PGTYPESnumeric_free(num); PGTYPESnumeric_free(num);
......
...@@ -228,7 +228,7 @@ if (sqlca.sqlcode < 0) exit (1);} ...@@ -228,7 +228,7 @@ if (sqlca.sqlcode < 0) exit (1);}
strcpy(msg, "insert"); strcpy(msg, "insert");
{ 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); { 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' , 'NaN' , 4 , 'd' , 4444444444444444444 ) , ( 5 , 'e' , 0.001234 , 5 , 'e' , 5555555555555555555 )", ECPGt_EOIT, ECPGt_EORT);
#line 99 "sqlda.pgc" #line 99 "sqlda.pgc"
if (sqlca.sqlcode < 0) exit (1);} if (sqlca.sqlcode < 0) exit (1);}
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 84: OK: CREATE TABLE [NO_PID]: ecpg_process_output on line 84: OK: CREATE TABLE
[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 94: query: 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 ); with 0 parameter(s) on connection regress1 [NO_PID]: ecpg_execute on line 94: query: 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' , 'NaN' , 4 , 'd' , 4444444444444444444 ) , ( 5 , 'e' , 0.001234 , 5 , 'e' , 5555555555555555555 ); with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 94: using PQexec [NO_PID]: ecpg_execute on line 94: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: sqlca: code: 0, state: 00000
......
...@@ -22,7 +22,7 @@ name sqlda descriptor: 'big' value 3333333333333333333 ...@@ -22,7 +22,7 @@ name sqlda descriptor: 'big' value 3333333333333333333
FETCH RECORD 4 FETCH RECORD 4
name sqlda descriptor: 'id' value 4 name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd' name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value NUMERIC '4.0' name sqlda descriptor: 'd1' value NUMERIC 'NaN'
name sqlda descriptor: 'd2' value 4.000000 name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd ' name sqlda descriptor: 'c' value 'd '
name sqlda descriptor: 'big' value 4444444444444444444 name sqlda descriptor: 'big' value 4444444444444444444
...@@ -57,7 +57,7 @@ name sqlda descriptor: 'big' value 3333333333333333333 ...@@ -57,7 +57,7 @@ name sqlda descriptor: 'big' value 3333333333333333333
FETCH RECORD 4 FETCH RECORD 4
name sqlda descriptor: 'id' value 4 name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd' name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value NUMERIC '4.0' name sqlda descriptor: 'd1' value NUMERIC 'NaN'
name sqlda descriptor: 'd2' value 4.000000 name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd ' name sqlda descriptor: 'c' value 'd '
name sqlda descriptor: 'big' value 4444444444444444444 name sqlda descriptor: 'big' value 4444444444444444444
...@@ -71,14 +71,14 @@ name sqlda descriptor: 'big' value 5555555555555555555 ...@@ -71,14 +71,14 @@ name sqlda descriptor: 'big' value 5555555555555555555
EXECUTE RECORD 4 EXECUTE RECORD 4
name sqlda descriptor: 'id' value 4 name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd' name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value NUMERIC '4.0' name sqlda descriptor: 'd1' value NUMERIC 'NaN'
name sqlda descriptor: 'd2' value 4.000000 name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd ' name sqlda descriptor: 'c' value 'd '
name sqlda descriptor: 'big' value 4444444444444444444 name sqlda descriptor: 'big' value 4444444444444444444
EXECUTE RECORD 4 EXECUTE RECORD 4
name sqlda descriptor: 'id' value 4 name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd' name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value NUMERIC '4.0' name sqlda descriptor: 'd1' value NUMERIC 'NaN'
name sqlda descriptor: 'd2' value 4.000000 name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd ' name sqlda descriptor: 'c' value 'd '
name sqlda descriptor: 'big' value 4444444444444444444 name sqlda descriptor: 'big' value 4444444444444444444
...@@ -95,7 +95,7 @@ exec sql end declare section; ...@@ -95,7 +95,7 @@ exec sql end declare section;
(1, 'a', 1.0, 1, 'a',1111111111111111111), (1, 'a', 1.0, 1, 'a',1111111111111111111),
(2, null, null, null, null,null), (2, null, null, null, null,null),
(3, 'c', 0.0, 3, 'c',3333333333333333333), (3, 'c', 0.0, 3, 'c',3333333333333333333),
(4, 'd', 4.0, 4, 'd',4444444444444444444), (4, 'd', 'NaN', 4, 'd',4444444444444444444),
(5, 'e', 0.001234, 5, 'e',5555555555555555555); (5, 'e', 0.001234, 5, 'e',5555555555555555555);
strcpy(msg, "commit"); strcpy(msg, "commit");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment