I'm trying to insert a row with a column that is an array of a custom type (ingredient
). My tables are:
CREATE TYPE ingredient AS (
name text,
quantity text,
unit text
);
CREATE TABLE IF NOT EXISTS recipes (
recipe_id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
name text,
ingredients ingredient[],
// ...
);
Using raw sql, I can insert a row by:
INSERT INTO recipes (name, ingredients) VALUES ('some_name', ARRAY[ROW('aa', 'bb', 'cc'), ROW('xx', 'yy', 'zz')]::ingredient[] );
But I'm struggling to do this in go with the pq
lib. I've created a pq.Array
interface:
type Ingredient struct {
Name string
Quantity string
Unit string
}
type Ingredients []*Ingredient
func (ings *Ingredients) ConvertValue(v interface{}) (driver.Value, error) {
return "something", nil
}
func (ings *Ingredients) Value() (driver.Value, error) {
val := `ARRAY[]`
for i, ing := range ings {
if i != 0 {
val += ","
}
val += fmt.Printf(`ROW('%v','%v','%v')`, ing.Name, ing.Quantity, ing.Unit)
}
val += `::ingredient[]`
return val, nil
}
// and then trying to insert via:
stmt := `INSERT INTO recipes (
name,
ingredients
)
VALUES ($1, $2)
`
_, err := db.Exec(stmt,
"some_name",
&Ingredients{
&Ingredient{"flour", "3", "cups"},
},
)
But pg keeps throwing the error:
Error insertingpq: malformed array literal: "ARRAY[ROW('flour','3','cups')]::ingredient[]"
Am I returning an incorrect driver.Value
?
You can either use this approach outlined here: https://github.com/lib/pq/issues/544
Or if you have records in the table and you query it, you will probably see the ingredient array in its literal form, which you can than mimic during insert.