- Notifications
You must be signed in to change notification settings - Fork515
Description
First, thank you for this incredible lib.
Second: I'm new to Rust and spinning up my first backend (DB + Webserver), so please feel free to redirect me other places if I can answer my own questions.
Problem
While the Postgresmoney
type isspecified in postgres-types, it doesn't appear to haveimpl To/FromSql
out of the box. I tried using floats and ints to convert, with no luck - lots of errors likecannot convert between the Rust type i32 and the Postgres type money
. I could implement these myself, but I wonder if they are simple enough to include in the library (if not by default, then perhaps as a feature).
From what I can tell from thePostgres docs on Monetary Types,it appears as though themoney
type is likely represented as an i64 of cents.
Rationale:
- Postgres docs list a range of -92233720368547758.08 to +92233720368547758.07. If you take the high number, you'll notice that it is (2^63)-1 / 100. So it seems like a good bet that Postgres is modeling the cents under the covers, but "rendering" in dollars.
Proposed Code Change
- Add
MONEY
to thesimple_from!
andsimple_to!
entries fori64
in src/lib.rs:
(Line563)simple_from!(i64, int8_from_sql,INT8,MONEY);(Line889)simple_to!(i64, int8_to_sql,INT8,MONEY);
I made this change to my local cargo lib, and was able to run a query against amoney
Postgres column and serialize it into an i64 struct field successfully. I have not tested the reverse path, going from Rust i64 to PG money column.
Snippets of the struct, impl, and Postgres table below:
pubstructAccount{id:Uuid,name:String,balance:i64,}implFrom<Row>forAccount{fnfrom(row:Row) ->Self{Self{id: row.get("id"),name: row.get("name"),balance: row.get("balance"),}}}
<localhost>=# \d accounts; Table"public.accounts" Column | Type | Collation | Nullable | Default---------+-----------------------+-----------+----------+-------------------- id | uuid | |not null | uuid_generate_v4() name |character varying(40) | |not null | balance |money | |not null |0
Open Questions:
- Is the macro the correct approach, or should
money
get it's own explicit impl? - Is this a common enough conversion to include by default, or should it be a feature?
- From the Postgres docs: "The fractional precision is determined by the database's lc_monetary setting." This seems like it could cause some wackiness.
- Further investigation would have to be done to ensure the conversion from Rust -> PG works as expected.
- Is i64 a good way to model money?