Skip to content

Instantly share code, notes, and snippets.

@rgalanakis
Created November 11, 2022 20:26
Show Gist options
  • Save rgalanakis/a2d5b8b61ee9540981bb43a103bf59c7 to your computer and use it in GitHub Desktop.
Save rgalanakis/a2d5b8b61ee9540981bb43a103bf59c7 to your computer and use it in GitHub Desktop.
Using postgres arrays with slices in goqu
package goqux
import (
"fmt"
"github.com/doug-martin/goqu/v9"
"strings"
)
// PGArrayExpr takes a slice of items and returns a literal expression
// with a Postgres array that can be used by goqu.
// It does this by using goqu natively and then manipulating the string
// to surround it in an array literal.
//
// To use this in a struct, you can do something like:
//
// type MyModel struct {
// Tags []string `json:"tags" db:"-"`
// DbTags goqu.Expression `json:"-" db:"tags"`
// }
// body := `{"tags":["x", "y"]}`
// m := MyModel{}
// _ = json.Unmarshal([]byte(body), &m)
// m.DbTags = goqux.PGArrayExpr(m.Tags)
// sql, _, _ := goqu.Insert("modeltable").Rows(m).ToSQL()
func PGArrayExpr[T any](arr []T) goqu.Expression {
if len(arr) == 0 {
return goqu.L("'{}'")
}
lit := goqu.V(arr)
selectSql, _, err := goqu.From(lit).ToSQL()
if err != nil {
panic(err)
}
valuesSql := strings.TrimPrefix(selectSql, "SELECT * FROM ")
if valuesSql == selectSql {
panic("expected go to output an (invalid) 'SELECT * FROM (x, y, z)' for the slice")
}
if valuesSql[0] != '(' || valuesSql[len(valuesSql)-1] != ')' {
panic("expected goqu to output '(x, y, z)' but is missing parens")
}
arraySql := fmt.Sprintf("ARRAY[%s]", valuesSql[1:len(valuesSql)-1])
return goqu.L(arraySql)
}
func ExamplePGArrayExprWithModel() {
type MyModel struct {
Tags []string `json:"tags" db:"-"`
DbTags goqu.Expression `json:"-" db:"tags"`
}
body := `{"tags":["x", "y"]}`
m := MyModel{}
_ = json.Unmarshal([]byte(body), &m)
m.DbTags = goqux.PGArrayExpr(m.Tags)
sql, _, _ := goqu.Insert("modeltable").Rows(m).ToSQL()
fmt.Println(sql)
// Output:
// INSERT INTO "modeltable" ("tags") VALUES (ARRAY['x', 'y'])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment