transformer: add transformer for unsetting empty values

This commit is contained in:
Nikita Karmatskikh
2021-11-26 01:42:25 +03:00
committed by Michal Jan Matczuk
parent 504f6523d9
commit e502c7cc40
2 changed files with 89 additions and 0 deletions

View File

@@ -19,6 +19,7 @@ import (
"github.com/scylladb/gocqlx/v2/qb"
"github.com/scylladb/gocqlx/v2/table"
"golang.org/x/sync/errgroup"
"gopkg.in/inf.v0"
)
// Running examples locally:
@@ -47,6 +48,7 @@ func TestExample(t *testing.T) {
pagingEfficientFullTableScan(t, session)
lwtLock(t, session)
unsetEmptyValues(t, session)
}
// This example shows how to use query builders and table models to build
@@ -705,6 +707,76 @@ func lwtLock(t *testing.T, session gocqlx.Session) {
}
}
// This example shows how to reuse the same insert statement with
// partially filled parameters without generating tombstones for empty columns.
func unsetEmptyValues(t *testing.T, session gocqlx.Session) {
err := session.ExecStmt(`CREATE KEYSPACE IF NOT EXISTS examples WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}`)
if err != nil {
t.Fatal("create keyspace:", err)
}
type Operation struct {
ID string
ClientID string
Type string
PaymentID string
Fee *inf.Dec
}
err = session.ExecStmt(`CREATE TABLE IF NOT EXISTS examples.operations (
id text PRIMARY KEY,
client_id text,
type text,
payment_id text,
fee decimal)`)
if err != nil {
t.Fatal("create table:", err)
}
insertOperation := qb.Insert("examples.operations").
Columns("id", "client_id", "type", "payment_id", "fee")
// Insert operation with empty paymentID.
insertQuery := insertOperation.Query(session).
WithBindTransformer(gocqlx.UnsetEmptyTransformer).
BindStruct(Operation{
ID: "1",
ClientID: "42",
Type: "Transfer",
Fee: inf.NewDec(1, 1),
})
if err := insertQuery.ExecRelease(); err != nil {
t.Fatal("ExecRelease() failed:", err)
}
// Set default transformer to avoid setting it for each query.
gocqlx.DefaultBindTransformer = gocqlx.UnsetEmptyTransformer
defer func() {
gocqlx.DefaultBindTransformer = nil
}()
// Insert operation with empty fee.
insertQuery = insertOperation.Query(session).
BindStruct(Operation{
ID: "2",
ClientID: "42",
Type: "Input",
PaymentID: "1",
})
if err := insertQuery.ExecRelease(); err != nil {
t.Fatal("ExecRelease() failed:", err)
}
// Query and displays data.
var ops []*Operation
if err := qb.Select("examples.operations").Query(session).Select(&ops); err != nil {
t.Fatal("Select() failed:", err)
}
for _, op := range ops {
t.Logf("%+v", *op)
}
}
func mustParseUUID(s string) gocql.UUID {
u, err := gocql.ParseUUID(s)
if err != nil {

View File

@@ -4,6 +4,12 @@
package gocqlx
import (
"reflect"
"github.com/gocql/gocql"
)
// Transformer transforms the value of the named parameter to another value.
type Transformer func(name string, val interface{}) interface{}
@@ -11,3 +17,14 @@ type Transformer func(name string, val interface{}) interface{}
//
// A custom transformer can always be set per Query.
var DefaultBindTransformer Transformer
// UnsetEmptyTransformer unsets all empty parameters.
// It helps to avoid tombstones when using the same insert/update
// statement for filled and partially filled named parameters.
var UnsetEmptyTransformer = func(name string, val interface{}) interface{} {
v := reflect.ValueOf(val)
if v.IsZero() {
return gocql.UnsetValue
}
return val
}