Repository: incubator-trafodion Updated Branches: refs/heads/master 0f838633f -> 4dfe27eba
fix TRAFODIION-2828 Project: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/commit/e89217ec Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/tree/e89217ec Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/diff/e89217ec Branch: refs/heads/master Commit: e89217ece4e3969b3c7da30adcdd4958d3fd2f98 Parents: ad9f4ef Author: SuJinpei <[email protected]> Authored: Tue Dec 5 16:04:29 2017 +0800 Committer: SuJinpei <[email protected]> Committed: Tue Dec 5 16:04:29 2017 +0800 ---------------------------------------------------------------------- .../odbc/odbcclient/unixcli/cli/drvrglobal.cpp | 112 +++++++------------ .../odbc/odbcclient/unixcli/cli/drvrglobal.h | 3 + 2 files changed, 42 insertions(+), 73 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/e89217ec/core/conn/unixodbc/odbc/odbcclient/unixcli/cli/drvrglobal.cpp ---------------------------------------------------------------------- diff --git a/core/conn/unixodbc/odbc/odbcclient/unixcli/cli/drvrglobal.cpp b/core/conn/unixodbc/odbc/odbcclient/unixcli/cli/drvrglobal.cpp index 975d66b..90fd4f3 100644 --- a/core/conn/unixodbc/odbc/odbcclient/unixcli/cli/drvrglobal.cpp +++ b/core/conn/unixodbc/odbc/odbcclient/unixcli/cli/drvrglobal.cpp @@ -917,79 +917,45 @@ bool use_gcvt(double number, char* string, short size) bool double_to_char (double number, int precision, char* string, short size) { - char *buffer,*temp ; - bool rc = true; - - int decimal_spot, - sign, - count, - current_location = 0, - length; - - *string = 0; - - temp = fcvt (number, precision, &decimal_spot, &sign) ; - length = strlen(temp); - if (length == 0) - { - return use_gcvt(number,string,size); - } - if (length > precision) - buffer = (char *) malloc (length + 3) ; - else - buffer = (char *) malloc (precision + 3) ; - - if (buffer == NULL) - return false; - -/* Add negative sign if required. */ - - if (sign) - buffer [current_location++] = '-' ; - -/* Place decimal point in the correct location. */ - - if (decimal_spot > 0) - { - strncpy (&buffer [current_location], temp, decimal_spot) ; - buffer [decimal_spot + current_location] = '.' ; - strcpy (&buffer [decimal_spot + current_location + 1], - &temp [decimal_spot]) ; - } - else - { - buffer [current_location] = '.' ; - for(count = current_location; - count< abs(decimal_spot)+current_location; count++) - buffer [count + 1] = '0' ; - strcpy (&buffer [count + 1], temp) ; - } - - rSup(buffer); - length = strlen(buffer); - if (buffer[0] == '.' || (buffer[0] == '-' && buffer[1] == '.')) length++; - - if (length>size) - rc = use_gcvt(number,string,size); - else - { - if (buffer[0] == '.') - { - strcpy( string, "0"); - strcat( string, buffer); - } - else if (buffer[0] == '-' && buffer[1] == '.') - { - strcpy( string, "-0"); - strcat( string, &buffer[1]); - } - - else - strcpy( string, buffer); - } - - free (buffer); - return rc; + bool rc = false; + char format[16] = { '\0' }; + size_t actualLen = 0; + + // make sure any precision of possible double value can be format to the buf. + char buf[MAX_DOUBLE_TO_CHAR_LEN] = { '\0' }; + + // precision should less than size + precision = precision < size ? precision : size - 1; + + // precission should be limit to a reasonable range. + if ((precision < 0) || (precision >(DBL_MANT_DIG - DBL_MIN_EXP))) { + goto fun_exit; + } + + // we want to return reasonable value even when caller didn't provide sufficiently buffer. + // here using loop because actualLen may increase even precision decrease when fix-point + // notation to exponential notation. for example: + // for double d = 12345678.9, the caller only provide size=8. + // d will first convert to "1.234568e+07", actualLen == 12. then convert to "1.2e+07". + do { + if (sprintf(format, "%%.%dlg", precision) < 0) { + goto fun_exit; + } + if ((actualLen = sprintf(buf, format, number)) < 0) { + goto fun_exit; + } + if (size > actualLen) { + strcpy(string, buf); + rc = true; + break; + } + else { + precision -= (actualLen - size + 1); + } + } while ((precision >= 0)); + +fun_exit: + return rc; } bool ctoi64(char* string, __int64& out, bool* truncation) http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/e89217ec/core/conn/unixodbc/odbc/odbcclient/unixcli/cli/drvrglobal.h ---------------------------------------------------------------------- diff --git a/core/conn/unixodbc/odbc/odbcclient/unixcli/cli/drvrglobal.h b/core/conn/unixodbc/odbc/odbcclient/unixcli/cli/drvrglobal.h index c082a46..395dfd6 100644 --- a/core/conn/unixodbc/odbc/odbcclient/unixcli/cli/drvrglobal.h +++ b/core/conn/unixodbc/odbc/odbcclient/unixcli/cli/drvrglobal.h @@ -36,6 +36,7 @@ #include "transportbase.h" #include "hpsqlext.h" #include <charsetconv.h> +#include "float.h" typedef int (*FPSQLGetPrivateProfileString) ( LPCSTR section, @@ -107,6 +108,8 @@ typedef int (*FPSQLGetPrivateProfileString) ( #define SQLERRWARN 1 #define ESTIMATEDCOSTRGERRWARN 2 +#define MAX_DOUBLE_TO_CHAR_LEN (DBL_MANT_DIG - DBL_MIN_EXP + 12) + typedef enum TRANSPORT_TYPE { TR_UNKNOWN = 0,
