Daniel Gustafsson писал(а) 2024-02-23 13:44:
On 22 Feb 2024, at 17:54, a.ima...@postgrespro.ru wrote:
PGTYPESnumeric_to_int() and PGTYPESnumeric_to_long()
functions return only 0 or -1. So ECPG_INFORMIX_NUM_OVERFLOW can never
be returned.
Indeed, this looks like an oversight.
I think dectoint(), dectolong() and PGTYPESnumeric_to_int() functions
should be a little bit different like in proposing patch.
What do you think?
- Convert a variable to type decimal to an integer.
+ Convert a variable of type decimal to an integer.
While related, this should be committed and backpatched regardless.
+ int errnum = 0;
Stylistic nit, we typically don't initialize a variable which cannot be
accessed before being set.
Overall the patch looks sane, please register it for the next
commitfest to
make it's not missed.
--
Daniel Gustafsson
Thank you for feedback,
- Convert a variable to type decimal to an integer.
+ Convert a variable of type decimal to an integer.
I removed this from the patch and proposed to
pgsql-d...@lists.postgresql.org
+ int errnum = 0;
fixed
Thank's for advice, the patch will be registered for the next
commitfest.
--
Aidar Imamov
diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml
index 73351a9136..aa86afa1d9 100644
--- a/doc/src/sgml/ecpg.sgml
+++ b/doc/src/sgml/ecpg.sgml
@@ -8892,8 +8892,9 @@ int dectoint(decimal *np, int *ip);
</para>
<para>
On success, 0 is returned and a negative value if the conversion
- failed. If an overflow occurred, <literal>ECPG_INFORMIX_NUM_OVERFLOW</literal>
- is returned.
+ failed. If overflow or underflow occurred, the function returns
+ <literal>ECPG_INFORMIX_NUM_OVERFLOW</literal> or
+ <literal>ECPG_INFORMIX_NUM_UNDERFLOW</literal> respectively.
</para>
<para>
Note that the ECPG implementation differs from the <productname>Informix</productname>
@@ -8918,8 +8919,9 @@ int dectolong(decimal *np, long *lngp);
</para>
<para>
On success, 0 is returned and a negative value if the conversion
- failed. If an overflow occurred, <literal>ECPG_INFORMIX_NUM_OVERFLOW</literal>
- is returned.
+ failed. If overflow or underflow occurred, the function returns
+ <literal>ECPG_INFORMIX_NUM_OVERFLOW</literal> or
+ <literal>ECPG_INFORMIX_NUM_UNDERFLOW</literal> respectively.
</para>
<para>
Note that the ECPG implementation differs from the <productname>Informix</productname>
diff --git a/src/interfaces/ecpg/compatlib/informix.c b/src/interfaces/ecpg/compatlib/informix.c
index 80d40aa3e0..5f9d71d0f3 100644
--- a/src/interfaces/ecpg/compatlib/informix.c
+++ b/src/interfaces/ecpg/compatlib/informix.c
@@ -434,6 +434,7 @@ int
dectoint(decimal *np, int *ip)
{
int ret;
+ int errnum;
numeric *nres = PGTYPESnumeric_new();
if (nres == NULL)
@@ -445,11 +446,18 @@ dectoint(decimal *np, int *ip)
return ECPG_INFORMIX_OUT_OF_MEMORY;
}
+ errno = 0;
ret = PGTYPESnumeric_to_int(nres, ip);
+ errnum = errno;
PGTYPESnumeric_free(nres);
- if (ret == PGTYPES_NUM_OVERFLOW)
- ret = ECPG_INFORMIX_NUM_OVERFLOW;
+ if (ret)
+ {
+ if (errnum == PGTYPES_NUM_UNDERFLOW)
+ ret = ECPG_INFORMIX_NUM_UNDERFLOW;
+ else if (errnum == PGTYPES_NUM_OVERFLOW)
+ ret = ECPG_INFORMIX_NUM_OVERFLOW;
+ }
return ret;
}
@@ -458,6 +466,7 @@ int
dectolong(decimal *np, long *lngp)
{
int ret;
+ int errnum;
numeric *nres = PGTYPESnumeric_new();
if (nres == NULL)
@@ -469,11 +478,18 @@ dectolong(decimal *np, long *lngp)
return ECPG_INFORMIX_OUT_OF_MEMORY;
}
+ errno = 0;
ret = PGTYPESnumeric_to_long(nres, lngp);
+ errnum = errno;
PGTYPESnumeric_free(nres);
- if (ret == PGTYPES_NUM_OVERFLOW)
- ret = ECPG_INFORMIX_NUM_OVERFLOW;
+ if (ret)
+ {
+ if (errnum == PGTYPES_NUM_UNDERFLOW)
+ ret = ECPG_INFORMIX_NUM_UNDERFLOW;
+ else if (errnum == PGTYPES_NUM_OVERFLOW)
+ ret = ECPG_INFORMIX_NUM_OVERFLOW;
+ }
return ret;
}
diff --git a/src/interfaces/ecpg/pgtypeslib/numeric.c b/src/interfaces/ecpg/pgtypeslib/numeric.c
index 35e7b92da4..52b49e1ce9 100644
--- a/src/interfaces/ecpg/pgtypeslib/numeric.c
+++ b/src/interfaces/ecpg/pgtypeslib/numeric.c
@@ -1502,7 +1502,12 @@ PGTYPESnumeric_to_int(numeric *nv, int *ip)
/* silence compilers that might complain about useless tests */
#if SIZEOF_LONG > SIZEOF_INT
- if (l < INT_MIN || l > INT_MAX)
+ if (l < INT_MIN)
+ {
+ errno = PGTYPES_NUM_UNDERFLOW;
+ return -1;
+ }
+ else if(l > INT_MAX)
{
errno = PGTYPES_NUM_OVERFLOW;
return -1;
diff --git a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout
index 1f8675b3f3..71a5afa4a7 100644
--- a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout
+++ b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout
@@ -3,8 +3,8 @@
(no errno set) - dec[0,3]: r: -1, *
(no errno set) - dec[0,4]: r: -1, *
dec[0,5]: r: 0, 0.00
-(errno == PGTYPES_NUM_OVERFLOW) - dec[0,6]: 0 (r: -1)
-(errno == PGTYPES_NUM_OVERFLOW) - dec[0,8]: 0 (r: -1)
+(errno == PGTYPES_NUM_OVERFLOW) - dec[0,6]: 0 (r: -1200)
+(errno == PGTYPES_NUM_OVERFLOW) - dec[0,8]: 0 (r: -1200)
(errno == PGTYPES_NUM_OVERFLOW) - dec[0,10]: 0 (r: -1)
dec[1,1]: r: 0, -2
@@ -45,8 +45,8 @@ dec[4,2]: r: 0, 592490000000000000000000
dec[4,3]: r: 0, 592490000000000000000000.0
dec[4,4]: r: 0, 592490000000000000000000.00
dec[4,5]: r: 0, 0.00
-(errno == PGTYPES_NUM_OVERFLOW) - dec[4,6]: 0 (r: -1)
-(errno == PGTYPES_NUM_OVERFLOW) - dec[4,8]: 0 (r: -1)
+(errno == PGTYPES_NUM_OVERFLOW) - dec[4,6]: 0 (r: -1200)
+(errno == PGTYPES_NUM_OVERFLOW) - dec[4,8]: 0 (r: -1200)
dec[4,10]: 5.9249e+23 (r: 0)
dec[5,1]: r: 0, -328400
@@ -141,8 +141,8 @@ dec[13,2]: r: 0, 1234567890123456789012345679
dec[13,3]: r: 0, 1234567890123456789012345678.9
dec[13,4]: r: 0, 1234567890123456789012345678.91
dec[13,5]: r: 0, 0.00
-(errno == PGTYPES_NUM_OVERFLOW) - dec[13,6]: 0 (r: -1)
-(errno == PGTYPES_NUM_OVERFLOW) - dec[13,8]: 0 (r: -1)
+(errno == PGTYPES_NUM_OVERFLOW) - dec[13,6]: 0 (r: -1200)
+(errno == PGTYPES_NUM_OVERFLOW) - dec[13,8]: 0 (r: -1200)
dec[13,10]: 1.23457e+27 (r: 0)
(errno == PGTYPES_NUM_OVERFLOW) - dec[14,0]: r: -1200