From 66c4e11023778972edc53f084a6c845790a64e26 Mon Sep 17 00:00:00 2001 From: zhang-wenzuo Date: Thu, 3 Jul 2025 14:42:30 +0800 Subject: [PATCH 1/3] fix ecpg decdiv/decmul numeric to decimal overflow error & add Test --- .../interfaces/ecpg/pgtypeslib/numeric.cpp | 48 +++++++++++++++++++ .../ecpg/test/compat_informix/dec_test.pgc | 20 ++++++++ .../compat_informix-dec_test-MinGW32.stdout | 3 ++ .../expected/compat_informix-dec_test.cpp | 20 ++++++++ .../expected/compat_informix-dec_test.stdout | 3 ++ 5 files changed, 94 insertions(+) diff --git a/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp b/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp index b1fcee87f..5437c2a36 100644 --- a/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp +++ b/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp @@ -1383,11 +1383,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..232562741 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,26 @@ main(void) } free(decarr); + decimal* dDqlx = PGTYPESdecimal_new(); + decimal* dJcjxts = PGTYPESdecimal_new(); + decimal* dtmp = PGTYPESdecimal_new(); + int retdecdiv = 0; + char* number1 = "53920000.0000000000000000000000"; + 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); + 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..74cb92a2e 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,6 @@ dec[d,14,14]: 1.00000000000000000 12: -0.5000001 13: 1234567890123456789012345678.91 14: +dDqlx = [539200000.0000000000000000000000] +dJcjxts = [360.0] +dtmp = [1497777.7777777777777777777778] 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..a9e4b4267 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,26 @@ main(void) } free(decarr); + decimal* dDqlx = PGTYPESdecimal_new(); + decimal* dJcjxts = PGTYPESdecimal_new(); + decimal* dtmp = PGTYPESdecimal_new(); + int retdecdiv = 0; + char* number1 = "53920000.0000000000000000000000"; + 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); + 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..0bb4a02a3 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,6 @@ dec[d,14,14]: 1.00000000000000000 12: -0.5000001 13: 1234567890123456789012345678.91 14: +dDqlx = [539200000.0000000000000000000000] +dJcjxts = [360.0] +dtmp = [1497777.7777777777777777777778] From b3be17c0f5e86b0de2dc3514df4a884f229576b9 Mon Sep 17 00:00:00 2001 From: zhang-wenzuo Date: Thu, 10 Jul 2025 14:57:53 +0800 Subject: [PATCH 2/3] fix ecpg div error --- .../interfaces/ecpg/pgtypeslib/numeric.cpp | 2 ++ .../ecpg/test/compat_informix/dec_test.pgc | 36 +++++++++++-------- .../compat_informix-dec_test-MinGW32.stdout | 5 +++ .../expected/compat_informix-dec_test.cpp | 36 +++++++++++-------- .../expected/compat_informix-dec_test.stdout | 5 +++ 5 files changed, 54 insertions(+), 30 deletions(-) diff --git a/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp b/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp index 5437c2a36..68f720f0f 100644 --- a/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp +++ b/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp @@ -989,6 +989,8 @@ int PGTYPESnumeric_div(numeric* var1, numeric* var2, numeric* result) init_numeric(÷nd); for (i = 1; i < 10; i++) { init_numeric(&divisor[i]); + + divisor[i].buf = NULL; } /* 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 232562741..b3f1ad732 100644 --- a/src/common/interfaces/ecpg/test/compat_informix/dec_test.pgc +++ b/src/common/interfaces/ecpg/test/compat_informix/dec_test.pgc @@ -206,25 +206,31 @@ main(void) } free(decarr); + char* desc[] = {"43920000.0000000000000000000000", "53920000.0000000000000000000000"}; decimal* dDqlx = PGTYPESdecimal_new(); decimal* dJcjxts = PGTYPESdecimal_new(); decimal* dtmp = PGTYPESdecimal_new(); int retdecdiv = 0; - char* number1 = "53920000.0000000000000000000000"; - 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); + int index = 0; + int breakTime = 2; + 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 74cb92a2e..d1438af5f 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,6 +1291,11 @@ 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] 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 a9e4b4267..e06848d71 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,25 +231,31 @@ main(void) } free(decarr); + char* desc[] = {"43920000.0000000000000000000000", "53920000.0000000000000000000000"}; decimal* dDqlx = PGTYPESdecimal_new(); decimal* dJcjxts = PGTYPESdecimal_new(); decimal* dtmp = PGTYPESdecimal_new(); int retdecdiv = 0; - char* number1 = "53920000.0000000000000000000000"; - 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); + int index = 0; + int breakTime = 2; + 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 0bb4a02a3..00ebac113 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,6 +1291,11 @@ 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] From 2df3644416626f66541315206859206d24cde2e8 Mon Sep 17 00:00:00 2001 From: zhang-wenzuo Date: Wed, 16 Jul 2025 15:38:30 +0800 Subject: [PATCH 3/3] fix numeric initial error --- src/common/interfaces/ecpg/pgtypeslib/numeric.cpp | 9 +++++++++ .../interfaces/ecpg/test/compat_informix/dec_test.pgc | 4 ++-- .../expected/compat_informix-dec_test-MinGW32.stdout | 4 ++++ .../ecpg/test/expected/compat_informix-dec_test.cpp | 4 ++-- .../ecpg/test/expected/compat_informix-dec_test.stdout | 4 ++++ 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp b/src/common/interfaces/ecpg/pgtypeslib/numeric.cpp index 68f720f0f..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,8 +993,10 @@ 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; 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 b3f1ad732..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,13 +206,13 @@ main(void) } free(decarr); - char* desc[] = {"43920000.0000000000000000000000", "53920000.0000000000000000000000"}; + 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 = 2; + int breakTime = 3; while (index < breakTime) { char* number1 = desc[index]; char* number2 = "360.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 d1438af5f..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 @@ -1299,3 +1299,7 @@ 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 e06848d71..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,13 +231,13 @@ main(void) } free(decarr); - char* desc[] = {"43920000.0000000000000000000000", "53920000.0000000000000000000000"}; + 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 = 2; + int breakTime = 3; while (index < breakTime) { char* number1 = desc[index]; char* number2 = "360.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 00ebac113..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 @@ -1299,3 +1299,7 @@ dDqlx = [539200000.0000000000000000000000] dJcjxts = [360.0] dtmp = [1497777.7777777777777777777778] dtmp = [19411200000.000000000000000000000000] +dDqlx = [720.0] +dJcjxts = [360.0] +dtmp = [2.0000000000000000] +dtmp = [259200.00]