transformer: add transformer for unsetting empty values
This commit is contained in:
committed by
Michal Jan Matczuk
parent
504f6523d9
commit
e502c7cc40
@@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/scylladb/gocqlx/v2/qb"
|
"github.com/scylladb/gocqlx/v2/qb"
|
||||||
"github.com/scylladb/gocqlx/v2/table"
|
"github.com/scylladb/gocqlx/v2/table"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
"gopkg.in/inf.v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Running examples locally:
|
// Running examples locally:
|
||||||
@@ -47,6 +48,7 @@ func TestExample(t *testing.T) {
|
|||||||
pagingEfficientFullTableScan(t, session)
|
pagingEfficientFullTableScan(t, session)
|
||||||
|
|
||||||
lwtLock(t, session)
|
lwtLock(t, session)
|
||||||
|
unsetEmptyValues(t, session)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This example shows how to use query builders and table models to build
|
// 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 {
|
func mustParseUUID(s string) gocql.UUID {
|
||||||
u, err := gocql.ParseUUID(s)
|
u, err := gocql.ParseUUID(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
|
|
||||||
package gocqlx
|
package gocqlx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/gocql/gocql"
|
||||||
|
)
|
||||||
|
|
||||||
// Transformer transforms the value of the named parameter to another value.
|
// Transformer transforms the value of the named parameter to another value.
|
||||||
type Transformer func(name string, val interface{}) interface{}
|
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.
|
// A custom transformer can always be set per Query.
|
||||||
var DefaultBindTransformer Transformer
|
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
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user