When I ran the test suite in lc_monetary = 'Japanise_Japan.932', following errors occured.
[excerpt]
X GetUpdateCommandInfersParametersWithNpgsqDbType [303ms]
error message:
Expected: 123.40000000000001d
But was: 1.23m
stack trace:
place Npgsql.Tests.CommandBuilderTests.GetUpdateCommandInfersParametersWithNpgsqDbType() 鍫存墍 C:\Users\k5user\source\repos\npgsql\test\Npgsql.Tests\CommandBuilderTests.cs:line 805
X Read("1.22::money",1.22m) [9ms]
error message:
Expected and actual are both <System.Int32[4]>
Values differ at index [0]
Expected: 122
But was: 1
stack trace:
place Npgsql.Tests.Types.MoneyTests.Read(String query, Decimal expected) 鍫存墍 C:\Users\k5user\source\repos\npgsql\test\Npgsql.Tests\Types\MoneyTests.cs: line 30
X Write("1.22::money",1.22m) [5ms]
error message:
Expected: True
But was: False
stack trace:
place Npgsql.Tests.Types.MoneyTests.Write(String query, Decimal expected) 鍫存墍 C:\Users\k5user\source\repos\npgsql\test\Npgsql.Tests\Types\MoneyTests.cs:line 45
etc...
_Originally posted by @GIriver in https://github.com/npgsql/npgsql/pull/2582#issuecomment-524679456_
I examine this issue.
MoneyHandler in Npgsql has const int MoneyScale = 2
, but the number of digits after the decimal point is different by lc_monetary in PostgreSQL data type money
(ex. ja_JP: digit=0 123, en_US: digit=2 123.45).
So when using lc_monetary whose number of digits after the decimal point is not equal to two, MoneyHandler returns incorrect number.
Thanks @GIriver! This is the first time that I see that a locale setting influences binary wire encoding in PostgreSQL...
Do you know if there's any way of knowing the scale from the locale value in lc_monetary? Or is the only option here to set up a table on our side?
Note: in theory we could simply send a cast from some number to money and examine the results. This could be done at first connection to a database for yet-unknown locales in lc_monetary, but it's pretty awful...
Sorry, I still don't come up with idea to solve this issue.
PostgreSQL gets the number of digits after the decimal point by using setlocale(), localeconv() and lconv->frac_digits(include locale.h). (ref https://doxygen.postgresql.org/cash_8c.html#a99c28c4652e488c10c3541962246d12f)
However, I don't know the way Npgsql gets PostgreSQL's money scale.
As you said, sending a money to PostgreSQL and recieving the money from PostgreSQL is the way to know money scale...
Most helpful comment
I examine this issue.
Problem
MoneyHandler in Npgsql has
const int MoneyScale = 2
, but the number of digits after the decimal point is different by lc_monetary in PostgreSQL data typemoney
(ex. ja_JP: digit=0 123, en_US: digit=2 123.45).So when using lc_monetary whose number of digits after the decimal point is not equal to two, MoneyHandler returns incorrect number.