Skip to content

v3.3.0

Compare
Choose a tag to compare
@xiam xiam released this 22 Jul 00:19
· 379 commits to master since this release

Changelog

Pagination

The new pagination API lets you split the results of a query into chunks containing a fixed number of items.

Simple pagination for db.Result

res = sess.Collection("posts").Paginate(20) // 20 results per page

err = res.All(&posts) // First 20 results of the query

err = res.Page(2).All(&posts) // Results from page 2 (limit 20, offset 40)

Simple pagination for SQL builder

q = sess.SelectFrom("posts").Paginate(20) 

err = res.All(&posts) // First 20 results of the query

err = res.Page(2).All(&posts) // Results from page 2 (limit 20, offset 40)

Cursor based pagination (both for db.Result and SQL Builder)

res = sess.Collection("posts").
  Paginate(20). // 20 results per page
  Cursor("id") // using id as cursor

err = res.All(&posts) // First 20 results of the query

// Get the next 20 results starting from the last item of the previous query.
res = res.NextPage(posts[len(posts)-1].ID)
err = res.All(&posts) // Results from page 1, limit 20, offset 20

Other commonly used pagination tools

res = res.Paginate(23)

totalNumberOfEntries, err = res.TotalEntries()

totalNumberOfPages, err = res.TotalPages()

Support for binary and text mode (PostgreSQL)

pgbouncer requires binary mode (binary_parameters="yes") to be enabled, but all of the auto-fields that were working with text mode started failing with binary mode.

Starting with v3.3.0 upper-db supports binary mode. This is how you can enable binary mode in your PostgreSQL session:

settings = postgresql.ConnectionURL {
  ...
  Options: map[string]string{
    "binary_parameters": "yes",
  },
}

Unfortunately, for this to work we had to push a breaking change: any fields that used stringarray, int64array and jsonb options need to be changed into an special type.

// Before v3.3.0 
type Demo struct {
   MyIntegers []int64 `db:"my_integers,int64array"`
   MyStrings []string `db:"my_strings,stringarray"`
   MyWhatevs map[string]interface{}`db:"field,jsonb"`
}
// v3.3.0+
type Demo struct {
   MyIntegers postgresql.Int64Array `db:"my_integers"`
   MyStrings postgresql.StringArray `db:"my_strings"`
   MyWhatevs postgresql.JSONBMap`db:"field"`
}

To make sure the user is aware of this, the mapping methods will now throw an error when stringarray, int64array or jsonb field tags are detected.

You can use any other custom struct as long as it satisfies driver.Valuer and sql.Scanner. The postgresql package providers some handy functions for when you want to encode something into JSONB format:

import (
  ...
  "database/sql/driver"
  "database/sql"

  "upper.io/db.v3/postgresql"
)

type Demo struct {
   MyWhatevs customJSONB `db:"field"`
}

type customJSONB struct {
	N string  `json:"name"`
	V float64 `json:"value"`
}

func (c customJSONB) Value() (driver.Value, error) {
	return postgresql.EncodeJSONB(c)
}

func (c *customJSONB) Scan(src interface{}) error {
	return postgresql.DecodeJSONB(c, src)
}

var (
	_ driver.Valuer = &customJSONB{}
	_ sql.Scanner = &customJSONB{}
)

Here are some other types provided by the postgresql package:

postgresql.Float64Array // []float64
postgresql.GenericArray // []interface{}
postgresql.BoolArray // []bool
postgresql.JSONB // interface{}
postgresql.JSONBMap // map[string]interface{}
postgresql.JSONBArray // []interface{}

Feel free to open a ticket if you find any bug or need help!