Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Precision issue, Double, Oracle DB #10047

Closed
lefebvrecharlie opened this issue Apr 6, 2020 · 5 comments
Closed

Precision issue, Double, Oracle DB #10047

lefebvrecharlie opened this issue Apr 6, 2020 · 5 comments

Comments

@lefebvrecharlie
Copy link

lefebvrecharlie commented Apr 6, 2020

Expected behavior and actual behavior:

Hi,

I have some precision issues after an upgrade to version 3.12.3 and last actual release 3.13.1, all was fine in 3.10.5.

I receive a response from another API to get some amounts, BigDecimal.

In my code, I set the scale to 2 with HALF_UP rounding mode.

In debug the value of myPojo is “1519.9”

myPojo.setValue(value.setScale(2, RoundingMode.HALF_UP).doubleValue());
pojoDao.insert(myPojo)

In the DB the value inserted is “1519.900000....1", the column type is FLOAT.

The DTO result from the other API
result

The table pojo to insert
pojo

The result into database
db

Thanks in advance :)

Versions:

  • jOOQ: 3.12.3, 3.13.1
  • Java: Java 11. (Open Jdk 11.0.6.10)
  • Database (include vendor): Oracle Database 12c Standard Edition Release 12.1.0.2.0 - 64bit Production
  • OS: Windows 10
  • JDBC Driver (include name if inofficial driver): oracle.jdbc.driver.OracleDriver 19.3
@lukaseder
Copy link
Member

Thank you very much for your report. We've fixed #7548 in jOOQ 3.11, by switching from binding to Oracle's BINARY_DOUBLE and BINARY_FLOAT APIs, instead of the standard JDBC APIs, this might explain it.

However, do note that when you're using floating point types, you will always get these rounding errors when trying to represent decimal numbers. What is the reason why you're storing monetary amount as FLOAT not as NUMBER?

@callain
Copy link

callain commented Apr 6, 2020

Thank you very much for the rapid answer ! It was specially hard to find for us as our integrations tests suites does not fetch values with the precision loss even if they are stored with a loss.

The main reason is legacy... I guess we need to fix the datatypes in order to upgrade.

@lukaseder
Copy link
Member

The main reason is legacy... I guess we need to fix the datatypes in order to upgrade.

You could use a custom data type binding for all FLOAT, BINARY_FLOAT, DOUBLE PRECISION, BINARY_DOUBLE columns that restores binding to default JDBC types:
https://www.jooq.org/doc/latest/manual/code-generation/custom-data-type-bindings

@lukaseder
Copy link
Member

... however, even if that works around the issue, the underlying latent problem is still there. IEEE 754 types cannot reliably store decimal values. There are workarounds and heuristics that you could apply: https://en.wikipedia.org/wiki/Decimal_floating_point

But ultimately, the NUMBER type (or BigDecimal in Java) will be the soundest way.

@lefebvrecharlie
Copy link
Author

Thanks a lot for your help !

@lukaseder lukaseder added this to To do in 3.14 Other improvements via automation Apr 7, 2020
@lukaseder lukaseder moved this from To do to Done in 3.14 Other improvements Jun 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

No branches or pull requests

3 participants