Skip to content

v3.4.0

Compare
Choose a tag to compare
@xiam xiam released this 19 Aug 13:33
· 351 commits to master since this release

Changelog for 3.4.0

Allow escaping ? marks inside queries

You can now escape ? marks inside queries by using ??:

// ...WHERE someColumn ? "Some Value"
col.Find().Where(`someColumn ?? ?`, "Some Value")

PostgreSQL: jsonb tag and JSONB values

Fields tagged with stringarray and int64array will no longer emit a deprecation message, as []string and []int64 will be converted automatically to the corresponding PostgreSQL array types like before. We recommend removing them anyways.

Fields tagged with jsonb will still emit an error when used, no matter what their type is they all need to satisfy sql.Scanner and driver.Valuer (or sqlbuilder.ScannerValuer).

We know that providing all those types with Scan(interface{}) error and Value() (driver.Value, error) by hand can be annoying, that's why we're providing this guide with common cases hoping that it might help you upgrading your codebase:

Structs

If your struct looks like:

type MyModel struct {
  ...
  MyField CustomStruct `db:"my_field,jsonb"`
}

type CustomStruct struct {
  Foo string `db:"foo"`
  ...
}

Change it into:

// 1. Import "upper.io/db.v3/postgresql"
import "upper.io/db.v3/postgresql"

type MyModel struct {
  ...
  MyField CustomStruct `db:"my_field,jsonb"`
}

type CustomStruct struct {
  Foo string `db:"foo"`
  ...
  // 2. Embed this type.
  *postgresql.JSONBConverter
}

// 3. (Optional) Import "upper.io/db.v3/lib/sqlbuilder" and add a compile-time type check
var _ sqlbuilder.ValueWrapper = &CustomStruct{}

Maps

If your struct looks like:

type MyModel struct {
  ...
  MyField map[string]interface{} `db:"my_field,jsonb"`
}

Change it into:

// 1. Import "upper.io/db.v3/postgresql"
import "upper.io/db.v3/postgresql"

type MyModel struct {
  ...
  // 2. Just remove "jsonb"
  MyField map[string]interface{} `db:"my_field"`
}

Interfaces

If your struct looks like:

type MyModel struct {
  ...
  MyField interface{} `db:"my_field,jsonb"`
}

Change it into:

// 1. Import "upper.io/db.v3/postgresql"
import "upper.io/db.v3/postgresql"

type MyModel struct {
  ...
  // 2. Change interface{} into postgresql.JSONB
  MyField postgresql.JSONB `db:"my_field,jsonb"`
}

You'll probably have to update more code and use myModel.MyField.V (the actual interface) instead of myModel.MyField.

Arrays

If your struct looks like:

type MyModel struct {
  ...
  MyField CustomStructArray `db:"my_field,jsonb"`
}

type CustomStructArray []CustomStruct

Change it into:

// 1. Import "upper.io/db.v3/postgresql"
import "upper.io/db.v3/postgresql"


type MyModel struct {
  ...
  MyField CustomStructArray `db:"my_field,jsonb"`
}

type CustomStructArray []CustomStruct

// 2. Add a WrapValue method to satisfy sqlbuilder.ValueWrapper
func (cs CustomStructArray) WrapValue(v interface{}) interface{} {
  return postgresql.Array(v)
}

// 3. Add Scan method to CustomStruct, if needed
func (c *CustomStruct) Scan(in interface{}) error {
  ...
}

Other types

Some types are going to be converted automatically to a proper type:

Go type PostgreSQL type
[]string TEXT[]
[]int64 INTEGER[]
[]bool BOOLEAN[]
[]float64 DOUBLE PRECISION[]
map[string]interface{} JSONB

Chances are you're using a different type, in that case you'll have to provide a proper driver.Valuer and sql.Scanner for them. If you're using a struct and embedding *postgresql.JSONBConverter does not solve your case, you can try with postgresql.JSONBValue and postgresql.ScanJSONB:

import (
  "database/sql/driver"
  "upper.io/db.v3/postgresql"
)

type Settings struct {
  Name string `json:"name"`
  Num  int64  `json:"num"`
}

func (s *Settings) Scan(src interface{}) error {
  return postgresql.ScanJSONB(s, src)
}
func (s Settings) Value() (driver.Value, error) {
  return postgresql.JSONBValue(s)
}

// var _ sqlbuilder.ScannerValuer = &Settings{} // Optional type check

Thanks

Thanks for using upper-db. Feel free to open a ticket if you need help.