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

Amount should implement driver.Valuer and sql.Scanner interfaces #9

Closed
bojanz opened this issue Feb 1, 2021 · 0 comments
Closed

Amount should implement driver.Valuer and sql.Scanner interfaces #9

bojanz opened this issue Feb 1, 2021 · 0 comments

Comments

@bojanz
Copy link
Owner

bojanz commented Feb 1, 2021

This would allow users on Postgres to define a composite type for prices, and scan it directly into currency.Amount.

Example composite type:

CREATE TYPE price AS (
   number NUMERIC, 
   currency_code CHAR(3)
);

Example usage in a table:

CREATE TABLE products (
   id CHAR(26) PRIMARY KEY,
   name TEXT NOT NULL,
   price price NOT NULL,
   created_at TIMESTAMPTZ NOT NULL,
   updated_at TIMESTAMPTZ
);

Example scan:

p := Product{}
row := tx.QueryRow(ctx, `SELECT id, name, price, created_at, updated_at FROM products WHERE id = $1`, id)
err := row.Scan(&p.ID, &p.Name, &p.Price, &p.CreatedAt, &p.UpdatedAt)

The two interface implementations would look something like this:

// Value implements the database/driver.Valuer interface.
func (a Amount) Value() (driver.Value, error) {
	return fmt.Sprintf("(%v,%v)", a.Number(), a.CurrencyCode()), nil
}

// Scan implements the database/sql.Scanner interface.
func (a *Amount) Scan(src interface{}) error {
	// Wire format: "(9.99,USD)".
	input := strings.Trim(src.(string), "()")
	values := strings.Split(input, ",")
        n := values[0]
        currencyCode := values[1]
        // Do something with the two strings.

	return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant