diff --git a/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp b/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp index b1fcee87f..fed246295 100644 --- a/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp +++ b/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp @@ -930,6 +930,13 @@ static int select_div_scale(numeric* var1, numeric* var2, int* rscale) return res_dscale; } +static void Initial_Numeric_Local(numeric *var1) +{ + int idx; + int total = sizeof(var1->local)/sizeof(var1->local[0]); + for (idx = 0; idx < total; idx++) { var1->local[idx] = 0; } +} + int PGTYPESnumeric_div(numeric* var1, numeric* var2, numeric* result) { NumericDigit* res_digits = NULL; @@ -986,9 +993,13 @@ int PGTYPESnumeric_div(numeric* var1, numeric* var2, numeric* result) /* * Initialize local variables */ + Initial_Numeric_Local(÷nd); init_numeric(÷nd); for (i = 1; i < 10; i++) { + Initial_Numeric_Local(&divisor[i]); init_numeric(&divisor[i]); + + divisor[i].buf = NULL; } /* @@ -1383,11 +1394,59 @@ int PGTYPESnumeric_to_long(numeric* nv, long* lp) return 0; } +static bool get_decimal_from_overflow_numeric(numeric* src, decimal* dst) +{ + bool result = false; + int radix = 10; + + if (src->sign == NUMERIC_NAN) { + /* this should not happen actually */ + src->ndigits = DECSIZE; + } else { + /* we must round up before convert the value */ + int total = src->dscale + src->weight + 1; + if (total >= 0) { + int size = DECSIZE; + int carry = (src->digits[size] > 4) ? 1 : 0; + + src->ndigits = DECSIZE; + + while (carry) { + carry += src->digits[--size]; + src->digits[size] = carry % radix; + carry /= radix; + } + + if (size < 0) { + src->digits--; + src->weight++; + } + } else { + src->ndigits = Max(0, Min(total, DECSIZE)); + } + } + + if (src->ndigits == DECSIZE) { + dst->weight = src->weight; + dst->rscale = src->rscale; + dst->dscale = src->dscale; + dst->sign = src->sign; + dst->ndigits = src->ndigits; + for (int i = 0; i < src->ndigits; i++) + dst->digits[i] = src->digits[i]; + result = true; + } + + return result; +} + int PGTYPESnumeric_to_decimal(numeric* src, decimal* dst) { int i; if (src->ndigits > DECSIZE) { + get_decimal_from_overflow_numeric(src, dst); + errno = PGTYPES_NUM_OVERFLOW; return -1; } diff --git a/src/common/interfaces/ecpg/test/compat_informix/dec_test.pgc b/src/common/interfaces/ecpg/test/compat_informix/dec_test.pgc index 56646694b..8377ce9eb 100644 --- a/src/common/interfaces/ecpg/test/compat_informix/dec_test.pgc +++ b/src/common/interfaces/ecpg/test/compat_informix/dec_test.pgc @@ -206,6 +206,32 @@ main(void) } free(decarr); + char* desc[] = {"43920000.0000000000000000000000", "53920000.0000000000000000000000", "720.0"}; + decimal* dDqlx = PGTYPESdecimal_new(); + decimal* dJcjxts = PGTYPESdecimal_new(); + decimal* dtmp = PGTYPESdecimal_new(); + int retdecdiv = 0; + int index = 0; + int breakTime = 3; + while (index < breakTime) { + char* number1 = desc[index]; + char* number2 = "360.0"; + retdecdiv = deccvasc(number1, strlen(number1), dDqlx); + retdecdiv = deccvasc(number2, strlen(number2), dJcjxts); + char printStr[60]; + dectoasc(dDqlx, printStr, sizeof(printStr) - 1, -1); + printf("dDqlx = [%s]\n", printStr); + dectoasc(dJcjxts, printStr, sizeof(printStr) - 1, -1); + printf("dJcjxts = [%s]\n", printStr); + retdecdiv = decdiv(dDqlx, dJcjxts, dtmp); + dectoasc(dtmp, printStr, sizeof(printStr) - 1, -1); + printf("dtmp = [%s]\n", printStr); + free(dDqlx); + free(dJcjxts); + free(dtmp); + index++; + } + return (0); } diff --git a/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test-MinGW32.stdout b/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test-MinGW32.stdout index 91faa2c04..3902321b9 100644 --- a/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test-MinGW32.stdout +++ b/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test-MinGW32.stdout @@ -1291,3 +1291,15 @@ dec[d,14,14]: 1.00000000000000000 12: -0.5000001 13: 1234567890123456789012345678.91 14: +dDqlx = [439200000.0000000000000000000000] +dJcjxts = [360.0] +dtmp = [122000.00000000000000000000000] +dtmp = [15811200000.000000000000000000000000] +dDqlx = [539200000.0000000000000000000000] +dJcjxts = [360.0] +dtmp = [1497777.7777777777777777777778] +dtmp = [19411200000.000000000000000000000000] +dDqlx = [720.0] +dJcjxts = [360.0] +dtmp = [2.0000000000000000] +dtmp = [259200.00] diff --git a/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test.cpp b/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test.cpp index 614ec3527..aeebd8fb5 100644 --- a/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test.cpp +++ b/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test.cpp @@ -231,6 +231,32 @@ main(void) } free(decarr); + char* desc[] = {"43920000.0000000000000000000000", "53920000.0000000000000000000000", "720.0"}; + decimal* dDqlx = PGTYPESdecimal_new(); + decimal* dJcjxts = PGTYPESdecimal_new(); + decimal* dtmp = PGTYPESdecimal_new(); + int retdecdiv = 0; + int index = 0; + int breakTime = 3; + while (index < breakTime) { + char* number1 = desc[index]; + char* number2 = "360.0"; + retdecdiv = deccvasc(number1, strlen(number1), dDqlx); + retdecdiv = deccvasc(number2, strlen(number2), dJcjxts); + char printStr[60]; + dectoasc(dDqlx, printStr, sizeof(printStr) - 1, -1); + printf("dDqlx = [%s]\n", printStr); + dectoasc(dJcjxts, printStr, sizeof(printStr) - 1, -1); + printf("dJcjxts = [%s]\n", printStr); + retdecdiv = decdiv(dDqlx, dJcjxts, dtmp); + dectoasc(dtmp, printStr, sizeof(printStr) - 1, -1); + printf("dtmp = [%s]\n", printStr); + free(dDqlx); + free(dJcjxts); + free(dtmp); + index++; + } + return (0); } diff --git a/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout b/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout index 4b29dcad4..a26400fd5 100644 --- a/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout +++ b/src/common/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout @@ -1291,3 +1291,15 @@ dec[d,14,14]: 1.00000000000000000 12: -0.5000001 13: 1234567890123456789012345678.91 14: +dDqlx = [439200000.0000000000000000000000] +dJcjxts = [360.0] +dtmp = [122000.00000000000000000000000] +dtmp = [15811200000.000000000000000000000000] +dDqlx = [539200000.0000000000000000000000] +dJcjxts = [360.0] +dtmp = [1497777.7777777777777777777778] +dtmp = [19411200000.000000000000000000000000] +dDqlx = [720.0] +dJcjxts = [360.0] +dtmp = [2.0000000000000000] +dtmp = [259200.00]