Created
November 11, 2022 20:26
-
-
Save rgalanakis/a2d5b8b61ee9540981bb43a103bf59c7 to your computer and use it in GitHub Desktop.
Using postgres arrays with slices in goqu
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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