Convert from cents to “price” and back
I do not want to use floats in the Go lang application, because it is
not supposed to do anything with these values other than to print and
retrieve them from the user; all computations will be performed by
PostgreSQL in cents.
That means i have to “convert” from the price format that users expect
to see (e.g., 1.234,56) to cents (e.g., 123456) and back when passing
data between Go and PostgreSQL, and that conversion depends on the
currency’s decimal places.
At first i did everything in Go, but saw that i would need to do it in
a loop when retrieving the list of products, and immediately knew it was
a mistake—i needed a PL/pgSQL function for that.
I still need to convert from string to float, however, when printing the
value to the user. Because the string representation is in C, but i
need to format it according to the locale with golang/x/text. That
package has the information of how to correctly format numbers, but it
is in an internal package that i can not use, and numbers.Digit only
accepts numeric types, not a string.
2023-02-05 12:55:12 +00:00
|
|
|
-- Test to_price
|
|
|
|
set client_min_messages to warning;
|
|
|
|
create extension if not exists pgtap;
|
|
|
|
reset client_min_messages;
|
|
|
|
|
|
|
|
begin;
|
|
|
|
|
2023-02-23 13:42:18 +00:00
|
|
|
select plan(29);
|
Convert from cents to “price” and back
I do not want to use floats in the Go lang application, because it is
not supposed to do anything with these values other than to print and
retrieve them from the user; all computations will be performed by
PostgreSQL in cents.
That means i have to “convert” from the price format that users expect
to see (e.g., 1.234,56) to cents (e.g., 123456) and back when passing
data between Go and PostgreSQL, and that conversion depends on the
currency’s decimal places.
At first i did everything in Go, but saw that i would need to do it in
a loop when retrieving the list of products, and immediately knew it was
a mistake—i needed a PL/pgSQL function for that.
I still need to convert from string to float, however, when printing the
value to the user. Because the string representation is in C, but i
need to format it according to the locale with golang/x/text. That
package has the information of how to correctly format numbers, but it
is in an internal package that i can not use, and numbers.Digit only
accepts numeric types, not a string.
2023-02-05 12:55:12 +00:00
|
|
|
|
|
|
|
set search_path to numerus, public;
|
|
|
|
|
|
|
|
select has_function('numerus', 'to_price', array ['integer', 'integer']);
|
|
|
|
select function_lang_is('numerus', 'to_price', array ['integer', 'integer'], 'plpgsql');
|
|
|
|
select function_returns('numerus', 'to_price', array ['integer', 'integer'], 'text');
|
|
|
|
select isnt_definer('numerus', 'to_price', array ['integer', 'integer']);
|
|
|
|
select volatility_is('numerus', 'to_price', array ['integer', 'integer'], 'immutable');
|
|
|
|
select function_privs_are('numerus', 'to_price', array ['integer', 'integer'], 'guest', array []::text[]);
|
|
|
|
select function_privs_are('numerus', 'to_price', array ['integer', 'integer'], 'invoicer', array ['EXECUTE']);
|
|
|
|
select function_privs_are('numerus', 'to_price', array ['integer', 'integer'], 'admin', array ['EXECUTE']);
|
|
|
|
select function_privs_are('numerus', 'to_price', array ['integer', 'integer'], 'authenticator', array []::text[]);
|
|
|
|
|
|
|
|
select is( to_price(0, 2), '0.00' );
|
|
|
|
select is( to_price(0, 3), '0.000' );
|
|
|
|
select is( to_price(1, 2), '0.01' );
|
|
|
|
select is( to_price(1, 3), '0.001' );
|
2023-02-23 13:42:18 +00:00
|
|
|
select is( to_price(-1, 2), '-0.01' );
|
|
|
|
select is( to_price(-1, 3), '-0.001' );
|
Convert from cents to “price” and back
I do not want to use floats in the Go lang application, because it is
not supposed to do anything with these values other than to print and
retrieve them from the user; all computations will be performed by
PostgreSQL in cents.
That means i have to “convert” from the price format that users expect
to see (e.g., 1.234,56) to cents (e.g., 123456) and back when passing
data between Go and PostgreSQL, and that conversion depends on the
currency’s decimal places.
At first i did everything in Go, but saw that i would need to do it in
a loop when retrieving the list of products, and immediately knew it was
a mistake—i needed a PL/pgSQL function for that.
I still need to convert from string to float, however, when printing the
value to the user. Because the string representation is in C, but i
need to format it according to the locale with golang/x/text. That
package has the information of how to correctly format numbers, but it
is in an internal package that i can not use, and numbers.Digit only
accepts numeric types, not a string.
2023-02-05 12:55:12 +00:00
|
|
|
select is( to_price(10, 2), '0.10' );
|
|
|
|
select is( to_price(10, 3), '0.010' );
|
|
|
|
select is( to_price(100, 2), '1.00' );
|
|
|
|
select is( to_price(100, 3), '0.100' );
|
|
|
|
select is( to_price(110, 2), '1.10' );
|
|
|
|
select is( to_price(1100, 3), '1.100' );
|
|
|
|
select is( to_price(12345678, 2), '123456.78' );
|
|
|
|
select is( to_price(12345678, 3), '12345.678' );
|
|
|
|
select is( to_price(12345678, 4), '1234.5678' );
|
|
|
|
select is( to_price(12345678, 5), '123.45678' );
|
2023-02-23 13:42:18 +00:00
|
|
|
select is( to_price(-12345678, 2), '-123456.78' );
|
|
|
|
select is( to_price(-12345678, 3), '-12345.678' );
|
|
|
|
select is( to_price(-12345678, 4), '-1234.5678' );
|
|
|
|
select is( to_price(-12345678, 5), '-123.45678' );
|
Convert from cents to “price” and back
I do not want to use floats in the Go lang application, because it is
not supposed to do anything with these values other than to print and
retrieve them from the user; all computations will be performed by
PostgreSQL in cents.
That means i have to “convert” from the price format that users expect
to see (e.g., 1.234,56) to cents (e.g., 123456) and back when passing
data between Go and PostgreSQL, and that conversion depends on the
currency’s decimal places.
At first i did everything in Go, but saw that i would need to do it in
a loop when retrieving the list of products, and immediately knew it was
a mistake—i needed a PL/pgSQL function for that.
I still need to convert from string to float, however, when printing the
value to the user. Because the string representation is in C, but i
need to format it according to the locale with golang/x/text. That
package has the information of how to correctly format numbers, but it
is in an internal package that i can not use, and numbers.Digit only
accepts numeric types, not a string.
2023-02-05 12:55:12 +00:00
|
|
|
|
|
|
|
select *
|
|
|
|
from finish();
|
|
|
|
|
|
|
|
rollback;
|