Home » U++ Library support » U++ SQL » Huge error of Postgresql! Double fields by transmission to the program lose a fractional part!
| Huge error of Postgresql! Double fields by transmission to the program lose a fractional part! [message #47491] |
Mon, 23 January 2017 02:28  |
|
|
Huge error of Postgresql!
Double fields by transmission to the program from sql table lose a fractional part!
The decision is extremely simple. To scan a string not as int (atoi), but as Double (ScanDouble).
The request to correct quickly as soon as it is possible!
Place to correct:
file PostgreSQL.cpp
Fucntion: void PostgreSQLConnection::GetColumn(int i, Ref f) const
Line: 644
Now:
switch(info[i].type)
{
case INT64_V:
f.SetValue(ScanInt64(s));
break;
case INT_V:
f.SetValue(atoi(s));
break;
case DOUBLE_V:
f.SetValue(atoi(s)); //<========THIS LINE NEED TO CORRECT
break;
case BOOL_V:
f.SetValue(*s == 't' ? "1" : "0");
break;
case DATE_V:
f.SetValue(sDate(s));
break;
case TIME_V: {
Time t = ToTime(sDate(s));
t.hour = atoi(s + 11);
t.minute = atoi(s + 14);
t.second = atoi(s + 17);
f.SetValue(t);
}
break;
default: {
. . . . .
Must be:
switch(info[i].type)
{
case INT64_V:
f.SetValue(ScanInt64(s));
break;
case INT_V:
f.SetValue(atoi(s));
break;
case DOUBLE_V:
f.SetValue(ScanDouble(s));
break;
case BOOL_V:
f.SetValue(*s == 't' ? "1" : "0");
break;
case DATE_V:
f.SetValue(sDate(s));
break;
case TIME_V: {
Time t = ToTime(sDate(s));
t.hour = atoi(s + 11);
t.minute = atoi(s + 14);
t.second = atoi(s + 17);
f.SetValue(t);
}
break;
default: {
. . . . .
Thanks!
SergeyNikitin<U++>( linux, wine )
{
under( Ubuntu || Debian || Raspbian );
}
|
|
|
|
|
|
|
|
|
|
|
|
| Re: Huge error of Postgresql! Double fields by transmission to the program lose a fractional part! [message #47514 is a reply to message #47499] |
Wed, 25 January 2017 11:30   |
 |
mirek
Messages: 14290 Registered: November 2005
|
Ultimate Member |
|
|
sergeynikitin wrote on Mon, 23 January 2017 09:46Yes. I can. I've Add myself to this issue.
I really wonder what U++ revision you are using, because in trunk it is:
void PostgreSQLConnection::GetColumn(int i, Ref f) const
{
if(PQgetisnull(result, fetched_row, i))
{
f = Null;
return;
}
char *s = PQgetvalue(result, fetched_row, i);
switch(info[i].type)
{
case INT64_V:
f.SetValue(ScanInt64(s));
break;
case INT_V:
f.SetValue(atoi(s));
break;
case DOUBLE_V:
f.SetValue(atof(s));
break;
and it is really really unlikely that this bug could get there in last 8 years, because in that period my major project is PGSQL and customers would really notice this within hours...
I have checked svn history and oldest revision available from 2009 has "atof" there...
Mirek
[Updated on: Wed, 25 January 2017 11:31] Report message to a moderator
|
|
|
|
| Re: Huge error of Postgresql! Double fields by transmission to the program lose a fractional part! [message #47519 is a reply to message #47514] |
Wed, 25 January 2017 18:18   |
|
|
mirek wrote on Wed, 25 January 2017 13:30sergeynikitin wrote on Mon, 23 January 2017 09:46Yes. I can. I've Add myself to this issue.
I really wonder what U++ revision you are using, because in trunk it is:
void PostgreSQLConnection::GetColumn(int i, Ref f) const
{
if(PQgetisnull(result, fetched_row, i))
{
f = Null;
return;
}
char *s = PQgetvalue(result, fetched_row, i);
switch(info[i].type)
{
case INT64_V:
f.SetValue(ScanInt64(s));
break;
case INT_V:
f.SetValue(atoi(s));
break;
case DOUBLE_V:
f.SetValue(atof(s));
break;
and it is really really unlikely that this bug could get there in last 8 years, because in that period my major project is PGSQL and customers would really notice this within hours...
I have checked svn history and oldest revision available from 2009 has "atof" there...
Mirek
I use summer svn code. (with c++11 support).
If all correct, - it's OK! I've locally corrected version of PostgreSQL.cpp.
SergeyNikitin<U++>( linux, wine )
{
under( Ubuntu || Debian || Raspbian );
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Re: Huge error of Postgresql! Double fields by transmission to the program lose a fractional part! [message #47532 is a reply to message #47531] |
Wed, 25 January 2017 20:40   |
 |
mirek
Messages: 14290 Registered: November 2005
|
Ultimate Member |
|
|
sergeynikitin wrote on Wed, 25 January 2017 20:31I'll try to prepare test case tonight .
You do not understand...
I need to know what your PostgreSQL instance returns (before atof), so that I am sure we are doing the right fix.
Because very likely the problem is that your PostgreSQL is configured somehow differently than my PostgreSQL.
So pretty please, place DUMP(s) before atof (or ScanDouble), like
switch(info[i].type)
{
case INT64_V:
f.SetValue(ScanInt64(s));
break;
case INT_V:
f.SetValue(atoi(s));
break;
case DOUBLE_V:
DUMP(s);
f.SetValue(ScanDouble(s));
break;
then post here a log (a couple of lines is enough).
Thanks,
Mirek
[Updated on: Wed, 25 January 2017 20:48] Report message to a moderator
|
|
|
|
|
|
| Re: Huge error of Postgresql! Double fields by transmission to the program lose a fractional part! [message #47535 is a reply to message #47534] |
Thu, 26 January 2017 01:25   |
|
|
Modified code (while lang settings SetLanguage(LNGFromText("RU-RU"));:
char *s = PQgetvalue(result, fetched_row, i);
switch(info[i].type)
{
case INT64_V:
f.SetValue(ScanInt64(s));
break;
case INT_V:
f.SetValue(atoi(s));
break;
case DOUBLE_V:
RLOG("===start analysis===");
RDUMP(s);
double da,dS;
da = atof(s);
dS = ScanDouble(s);
RDUMP(da);
RDUMP(dS);
static String test_format_and_lang_settings;
test_format_and_lang_settings = Format("%f",dS);
RDUMP(test_format_and_lang_settings);
RLOG("====end analysis====");
RLOG(" ");
f.SetValue(ScanDouble(s));
break;
case BOOL_V:
f.SetValue(*s == 't' ? "1" : "0");
break;
case DATE_V:
Log:
26.01.2017 03:22:15 ===start analysis===
26.01.2017 03:22:15 s = 90
26.01.2017 03:22:15 da = 90
26.01.2017 03:22:15 dS = 90
26.01.2017 03:22:15 test_format_and_lang_settings = 90,000000
26.01.2017 03:22:15 ====end analysis====
26.01.2017 03:22:15
26.01.2017 03:22:15 ===start analysis===
26.01.2017 03:22:15 s = 40
26.01.2017 03:22:15 da = 40
26.01.2017 03:22:15 dS = 40
26.01.2017 03:22:15 test_format_and_lang_settings = 40,000000
26.01.2017 03:22:15 ====end analysis====
26.01.2017 03:22:15
26.01.2017 03:22:15 ===start analysis===
26.01.2017 03:22:15 s = 269.96336996337
26.01.2017 03:22:15 da = 269
26.01.2017 03:22:15 dS = 269.96336996337
26.01.2017 03:22:15 test_format_and_lang_settings = 269,963370
26.01.2017 03:22:15 ====end analysis====
26.01.2017 03:22:15
26.01.2017 03:22:15 ===start analysis===
26.01.2017 03:22:15 s = 381.556455240666
26.01.2017 03:22:15 da = 381
26.01.2017 03:22:15 dS = 381.556455240666
26.01.2017 03:22:15 test_format_and_lang_settings = 381,556455
26.01.2017 03:22:15 ====end analysis====
26.01.2017 03:22:15
26.01.2017 03:22:15 ===start analysis===
26.01.2017 03:22:15 s = 282.083413662361
26.01.2017 03:22:15 da = 282
26.01.2017 03:22:15 dS = 282.083413662361
26.01.2017 03:22:15 test_format_and_lang_settings = 282,083414
26.01.2017 03:22:15 ====end analysis====
SergeyNikitin<U++>( linux, wine )
{
under( Ubuntu || Debian || Raspbian );
}
[Updated on: Thu, 26 January 2017 01:28] Report message to a moderator
|
|
|
|
| Re: Huge error of Postgresql! Double fields by transmission to the program lose a fractional part! [message #47536 is a reply to message #47535] |
Thu, 26 January 2017 01:33   |
|
|
While lang settings SetLanguage(LNGFromText("EN-US");:
26.01.2017 03:26:34 ===start analysis===
26.01.2017 03:26:34 s = 40
26.01.2017 03:26:34 da = 40
26.01.2017 03:26:34 dS = 40
26.01.2017 03:26:34 test_format_and_lang_settings = 40,000000
26.01.2017 03:26:34 ====end analysis====
26.01.2017 03:26:34
26.01.2017 03:26:34 ===start analysis===
26.01.2017 03:26:34 s = 269.96336996337
26.01.2017 03:26:34 da = 269
26.01.2017 03:26:34 dS = 269.96336996337
26.01.2017 03:26:34 test_format_and_lang_settings = 269,963370
26.01.2017 03:26:34 ====end analysis====
26.01.2017 03:26:34
26.01.2017 03:26:34 ===start analysis===
26.01.2017 03:26:34 s = 59.95115995116
26.01.2017 03:26:34 da = 59
26.01.2017 03:26:34 dS = 59.95115995116
26.01.2017 03:26:34 test_format_and_lang_settings = 59,951160
26.01.2017 03:26:34 ====end analysis====
26.01.2017 03:26:34
26.01.2017 03:26:34 ===start analysis===
26.01.2017 03:26:34 s = 222.435897435897
26.01.2017 03:26:34 da = 222
26.01.2017 03:26:34 dS = 222.435897435897
26.01.2017 03:26:34 test_format_and_lang_settings = 222,435897
26.01.2017 03:26:34 ====end analysis====
26.01.2017 03:26:34
Both test under UBUNTU 16.04 (with Russian main language)
SergeyNikitin<U++>( linux, wine )
{
under( Ubuntu || Debian || Raspbian );
}
[Updated on: Thu, 26 January 2017 01:52] Report message to a moderator
|
|
|
|
| Re: Huge error of Postgresql! Double fields by transmission to the program lose a fractional part! [message #47537 is a reply to message #47536] |
Thu, 26 January 2017 01:43   |
|
|
But if I start
LC_ALL=en_US.UTF-8 ./ProgramName
or
LANG=en_US.UTF-8 ./ProgramName
than all correct.
26.01.2017 03:41:15 ===start analysis===
26.01.2017 03:41:15 s = 40
26.01.2017 03:41:15 da = 40
26.01.2017 03:41:15 dS = 40
26.01.2017 03:41:15 test_format_and_lang_settings = 40.000000
26.01.2017 03:41:15 ====end analysis====
26.01.2017 03:41:15
26.01.2017 03:41:15 ===start analysis===
26.01.2017 03:41:15 s = 269.96336996337
26.01.2017 03:41:15 da = 269.96336996337
26.01.2017 03:41:15 dS = 269.96336996337
26.01.2017 03:41:15 test_format_and_lang_settings = 269.963370
26.01.2017 03:41:15 ====end analysis====
26.01.2017 03:41:15
26.01.2017 03:41:15 ===start analysis===
26.01.2017 03:41:15 s = 59.95115995116
26.01.2017 03:41:15 da = 59.95115995116
26.01.2017 03:41:15 dS = 59.95115995116
26.01.2017 03:41:15 test_format_and_lang_settings = 59.951160
26.01.2017 03:41:15 ====end analysis====
26.01.2017 03:41:15
SergeyNikitin<U++>( linux, wine )
{
under( Ubuntu || Debian || Raspbian );
}
[Updated on: Thu, 26 January 2017 01:50] Report message to a moderator
|
|
|
|
|
|
| Re: Huge error of Postgresql! Double fields by transmission to the program lose a fractional part! [message #47539 is a reply to message #47538] |
Thu, 26 January 2017 01:57   |
|
|
Postgresql (Server v. 9.5) language settings are default.
fragment of postgres config:
# These settings are initialized by initdb, but they can be changed.
lc_messages = 'ru_RU.UTF-8' # locale for system error message
# strings
lc_monetary = 'ru_RU.UTF-8' # locale for monetary formatting
lc_numeric = 'ru_RU.UTF-8' # locale for number formatting
lc_time = 'ru_RU.UTF-8' # locale for time formatting
SergeyNikitin<U++>( linux, wine )
{
under( Ubuntu || Debian || Raspbian );
}
|
|
|
|
| Re: Huge error of Postgresql! Double fields by transmission to the program lose a fractional part! [message #47540 is a reply to message #47539] |
Thu, 26 January 2017 02:04   |
|
|
I change postgresql setting to ( /etc/postgresql/9.5/main/postgresql.conf )
en_US:
# These settings are initialized by initdb, but they can be changed.
#lc_messages = 'ru_RU.UTF-8' # locale for system error message
# strings
#lc_monetary = 'ru_RU.UTF-8' # locale for monetary formatting
#lc_numeric = 'ru_RU.UTF-8' # locale for number formatting
#lc_time = 'ru_RU.UTF-8' # locale for time formatting
lc_messages = 'en_US.UTF-8' # locale for system error message
# strings
lc_monetary = 'en_US.UTF-8' # locale for monetary formatting
lc_numeric = 'en_US.UTF-8' # locale for number formatting
lc_time = 'en_US.UTF-8' # locale for time formatting
Result is zero!
26.01.2017 03:59:52 ===start analysis===
26.01.2017 03:59:52 s = 40
26.01.2017 03:59:52 da = 40
26.01.2017 03:59:52 dS = 40
26.01.2017 03:59:52 test_format_and_lang_settings = 40,000000
26.01.2017 03:59:52 ====end analysis====
26.01.2017 03:59:52
26.01.2017 03:59:52 ===start analysis===
26.01.2017 03:59:52 s = 269.96336996337
26.01.2017 03:59:52 da = 269
26.01.2017 03:59:52 dS = 269.96336996337
26.01.2017 03:59:52 test_format_and_lang_settings = 269,963370
26.01.2017 03:59:52 ====end analysis====
26.01.2017 03:59:52
26.01.2017 03:59:52 ===start analysis===
26.01.2017 03:59:52 s = 59.95115995116
26.01.2017 03:59:52 da = 59
26.01.2017 03:59:52 dS = 59.95115995116
26.01.2017 03:59:52 test_format_and_lang_settings = 59,951160
26.01.2017 03:59:52 ====end analysis====
SergeyNikitin<U++>( linux, wine )
{
under( Ubuntu || Debian || Raspbian );
}
|
|
|
|
| Re: Huge error of Postgresql! Double fields by transmission to the program lose a fractional part! [message #47541 is a reply to message #47540] |
Thu, 26 January 2017 02:23   |
|
|
I test timings:
Test code:
#include <Core/Core.h>
using namespace Upp;
CONSOLE_APP_MAIN
{
double a;
String s = "269.96336996337";
#define LOOPS 1000000
for(int i = 0; i < LOOPS; i++){
RTIMING("Using atof");
a = atof(s);
}
for(int i = 0; i < LOOPS; i++){
RTIMING("Using ScanDouble");
a = ScanDouble(s);
}
}
TIMING results:
TIMING Using ScanDouble: 1.12 s - 1.12 us ( 1.22 s / 1000000 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 1000000
TIMING Using atof : 337.45 ms - 337.45 ns (439.00 ms / 1000000 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 1000000
It's not dramatically slower! But standard settings (on various environments) show right results!
SergeyNikitin<U++>( linux, wine )
{
under( Ubuntu || Debian || Raspbian );
}
|
|
|
|
|
|
| Re: Huge error of Postgresql! Double fields by transmission to the program lose a fractional part! [message #47544 is a reply to message #47541] |
Thu, 26 January 2017 14:10   |
 |
mirek
Messages: 14290 Registered: November 2005
|
Ultimate Member |
|
|
sergeynikitin wrote on Thu, 26 January 2017 02:23I test timings:
Test code:
#include <Core/Core.h>
using namespace Upp;
CONSOLE_APP_MAIN
{
double a;
String s = "269.96336996337";
#define LOOPS 1000000
for(int i = 0; i < LOOPS; i++){
RTIMING("Using atof");
a = atof(s);
}
for(int i = 0; i < LOOPS; i++){
RTIMING("Using ScanDouble");
a = ScanDouble(s);
}
}
TIMING results:
TIMING Using ScanDouble: 1.12 s - 1.12 us ( 1.22 s / 1000000 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 1000000
TIMING Using atof : 337.45 ms - 337.45 ns (439.00 ms / 1000000 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 1000000
It's not dramatically slower! But standard settings (on various environments) show right results!
BTW, have you tried in Release? MSC14 32-bit release I am getting:
TIMING Using ScanDouble: 120.72 ms - 120.72 ns (148.00 ms / 1000000 ), min: 0.00 ns, max: 2.00 ms, nesting: 1 - 1000000
TIMING Using atof : 281.72 ms - 281.72 ns (309.00 ms / 1000000 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 1000000
I really would not like U++ being slower... 
|
|
|
|
|
|
|
|
Goto Forum:
Current Time: Mon Apr 27 10:11:36 GMT+2 2026
Total time taken to generate the page: 0.01393 seconds
|