]> granicus.if.org Git - postgresql/commitdiff
Second try at fixing numeric data passed through an ECPG SQLDA.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 14 Nov 2018 16:27:30 +0000 (11:27 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 14 Nov 2018 16:27:47 +0000 (11:27 -0500)
In commit ecfd55795, 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
f2ae9f9c3) 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

src/interfaces/ecpg/ecpglib/sqlda.c
src/interfaces/ecpg/test/expected/sql-sqlda.c
src/interfaces/ecpg/test/expected/sql-sqlda.stderr
src/interfaces/ecpg/test/expected/sql-sqlda.stdout
src/interfaces/ecpg/test/sql/sqlda.pgc

index 3f86af3c8c4d02e1af1d7547589ec606ae8496a1..80ddc6b6b13b74f5130fea2989d724f69d1e3032 100644 (file)
@@ -123,7 +123,8 @@ sqlda_common_total_size(const PGresult *res, int row, enum COMPAT_MODE compat, l
                                        num = PGTYPESnumeric_from_asc(val, NULL);
                                        if (!num)
                                                break;
-                                       ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
+                                       if (num->buf)
+                                               ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
                                        PGTYPESnumeric_free(num);
                                }
                                break;
@@ -347,11 +348,14 @@ ecpg_set_compat_sqlda(int lineno, struct sqlda_compat **_sqlda, const PGresult *
 
                                        memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
 
-                                       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);
+                                       if (num->buf)
+                                       {
+                                               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);
 
-                                       ((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)->buf = (NumericDigit *) sqlda + offset;
+                                               ((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
+                                       }
 
                                        PGTYPESnumeric_free(num);
 
@@ -533,11 +537,14 @@ ecpg_set_native_sqlda(int lineno, struct sqlda_struct **_sqlda, const PGresult *
 
                                        memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
 
-                                       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);
+                                       if (num->buf)
+                                       {
+                                               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);
 
-                                       ((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)->buf = (NumericDigit *) sqlda + offset;
+                                               ((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
+                                       }
 
                                        PGTYPESnumeric_free(num);
 
index 3cba69e1a58b30378ad9a9f506bf19d0b498cf0e..6bd9d5527a0b89990661fe4dccd0d9307821c957 100644 (file)
@@ -228,7 +228,7 @@ if (sqlca.sqlcode < 0) exit (1);}
 
 
        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"
 
 if (sqlca.sqlcode < 0) exit (1);}
index 2545aa1a0b38aaf9b0b071fa58f47ed7b083b443..e8c7a3725ea17b0f388b1922b0a69827f06381d6 100644 (file)
@@ -14,7 +14,7 @@
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_process_output on line 84: OK: CREATE TABLE
 [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]: ecpg_execute on line 94: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
index 81a5978b1c126a4d4af9497173e4a01cd4515b34..e3b1a6484aa3952dc9eca14e2ccb76a25af42321 100644 (file)
@@ -22,7 +22,7 @@ name sqlda descriptor: 'big' value 3333333333333333333
 FETCH RECORD 4
 name sqlda descriptor: 'id' value 4
 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: 'c' value 'd         '
 name sqlda descriptor: 'big' value 4444444444444444444
@@ -57,7 +57,7 @@ name sqlda descriptor: 'big' value 3333333333333333333
 FETCH RECORD 4
 name sqlda descriptor: 'id' value 4
 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: 'c' value 'd         '
 name sqlda descriptor: 'big' value 4444444444444444444
@@ -71,14 +71,14 @@ name sqlda descriptor: 'big' value 5555555555555555555
 EXECUTE RECORD 4
 name sqlda descriptor: 'id' value 4
 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: 'c' value 'd         '
 name sqlda descriptor: 'big' value 4444444444444444444
 EXECUTE RECORD 4
 name sqlda descriptor: 'id' value 4
 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: 'c' value 'd         '
 name sqlda descriptor: 'big' value 4444444444444444444
index 4c3abca9d1bace3aa0ae4bd832f3974a0c0ee227..f54b7e3c94b17023b4af54e61f1e577c62045a9b 100644 (file)
@@ -95,7 +95,7 @@ exec sql end declare section;
                (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),
+               (4, 'd', 'NaN', 4, 'd',4444444444444444444),
                (5, 'e', 0.001234, 5, 'e',5555555555555555555);
 
        strcpy(msg, "commit");