@@ -61,13 +61,12 @@ func TestExample(t *testing.T) {
|
|||||||
{
|
{
|
||||||
stmt, names := qb.Insert("gocqlx_test.person").
|
stmt, names := qb.Insert("gocqlx_test.person").
|
||||||
Columns("first_name", "last_name", "email").
|
Columns("first_name", "last_name", "email").
|
||||||
TTL().
|
TTL(86400 * time.Second).
|
||||||
|
Timestamp(time.Now()).
|
||||||
ToCql()
|
ToCql()
|
||||||
|
|
||||||
q := gocqlx.Query(session.Query(stmt), names).BindStructMap(p, qb.M{
|
err := gocqlx.Query(session.Query(stmt), names).BindStruct(p).ExecRelease()
|
||||||
"_ttl": qb.TTL(86400 * time.Second),
|
if err != nil {
|
||||||
})
|
|
||||||
if err := q.ExecRelease(); err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
qb/batch.go
26
qb/batch.go
@@ -7,6 +7,7 @@ package qb
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BATCH reference:
|
// BATCH reference:
|
||||||
@@ -98,14 +99,27 @@ func (b *BatchBuilder) Counter() *BatchBuilder {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamp sets a USING TIMESTAMP clause on the query.
|
// TTL adds USING TTL clause to the query.
|
||||||
func (b *BatchBuilder) Timestamp() *BatchBuilder {
|
func (b *BatchBuilder) TTL(d time.Duration) *BatchBuilder {
|
||||||
b.using.timestamp = true
|
b.using.TTL(d)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// TTL sets a USING TTL clause on the query.
|
// TTLNamed adds USING TTL clause to the query with a custom parameter name.
|
||||||
func (b *BatchBuilder) TTL() *BatchBuilder {
|
func (b *BatchBuilder) TTLNamed(name string) *BatchBuilder {
|
||||||
b.using.ttl = true
|
b.using.TTLNamed(name)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timestamp adds USING TIMESTAMP clause to the query.
|
||||||
|
func (b *BatchBuilder) Timestamp(t time.Time) *BatchBuilder {
|
||||||
|
b.using.Timestamp(t)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampNamed adds a USING TIMESTAMP clause to the query with a custom
|
||||||
|
// parameter name.
|
||||||
|
func (b *BatchBuilder) TimestampNamed(name string) *BatchBuilder {
|
||||||
|
b.using.TimestampNamed(name)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package qb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
)
|
)
|
||||||
@@ -53,15 +54,23 @@ func TestBatchBuilder(t *testing.T) {
|
|||||||
},
|
},
|
||||||
// Add TTL
|
// Add TTL
|
||||||
{
|
{
|
||||||
B: Batch().TTL(),
|
B: Batch().TTL(time.Second),
|
||||||
|
S: "BEGIN BATCH USING TTL 1 APPLY BATCH ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
B: Batch().TTLNamed("ttl"),
|
||||||
S: "BEGIN BATCH USING TTL ? APPLY BATCH ",
|
S: "BEGIN BATCH USING TTL ? APPLY BATCH ",
|
||||||
N: []string{"_ttl"},
|
N: []string{"ttl"},
|
||||||
},
|
},
|
||||||
// Add TIMESTAMP
|
// Add TIMESTAMP
|
||||||
{
|
{
|
||||||
B: Batch().Timestamp(),
|
B: Batch().Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)),
|
||||||
|
S: "BEGIN BATCH USING TIMESTAMP 1115251200000000 APPLY BATCH ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
B: Batch().TimestampNamed("ts"),
|
||||||
S: "BEGIN BATCH USING TIMESTAMP ? APPLY BATCH ",
|
S: "BEGIN BATCH USING TIMESTAMP ? APPLY BATCH ",
|
||||||
N: []string{"_ts"},
|
N: []string{"ts"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
qb/cmp.go
22
qb/cmp.go
@@ -297,3 +297,25 @@ func (cs cmps) writeCql(cql *bytes.Buffer) (names []string) {
|
|||||||
cql.WriteByte(' ')
|
cql.WriteByte(' ')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type where cmps
|
||||||
|
|
||||||
|
func (w where) writeCql(cql *bytes.Buffer) (names []string) {
|
||||||
|
if len(w) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cql.WriteString("WHERE ")
|
||||||
|
return cmps(w).writeCql(cql)
|
||||||
|
}
|
||||||
|
|
||||||
|
type _if cmps
|
||||||
|
|
||||||
|
func (w _if) writeCql(cql *bytes.Buffer) (names []string) {
|
||||||
|
if len(w) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cql.WriteString("IF ")
|
||||||
|
return cmps(w).writeCql(cql)
|
||||||
|
}
|
||||||
|
|||||||
14
qb/delete.go
14
qb/delete.go
@@ -9,6 +9,7 @@ package qb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeleteBuilder builds CQL DELETE statements.
|
// DeleteBuilder builds CQL DELETE statements.
|
||||||
@@ -65,9 +66,16 @@ func (b *DeleteBuilder) Columns(columns ...string) *DeleteBuilder {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamp sets a USING TIMESTAMP clause on the query.
|
// Timestamp adds USING TIMESTAMP clause to the query.
|
||||||
func (b *DeleteBuilder) Timestamp() *DeleteBuilder {
|
func (b *DeleteBuilder) Timestamp(t time.Time) *DeleteBuilder {
|
||||||
b.using.timestamp = true
|
b.using.Timestamp(t)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampNamed adds a USING TIMESTAMP clause to the query with a custom
|
||||||
|
// parameter name.
|
||||||
|
func (b *DeleteBuilder) TimestampNamed(name string) *DeleteBuilder {
|
||||||
|
b.using.TimestampNamed(name)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package qb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
)
|
)
|
||||||
@@ -50,9 +51,14 @@ func TestDeleteBuilder(t *testing.T) {
|
|||||||
},
|
},
|
||||||
// Add TIMESTAMP
|
// Add TIMESTAMP
|
||||||
{
|
{
|
||||||
B: Delete("cycling.cyclist_name").Where(w).Timestamp(),
|
B: Delete("cycling.cyclist_name").Where(w).Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)),
|
||||||
|
S: "DELETE FROM cycling.cyclist_name USING TIMESTAMP 1115251200000000 WHERE id=? ",
|
||||||
|
N: []string{"expr"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
B: Delete("cycling.cyclist_name").Where(w).TimestampNamed("ts"),
|
||||||
S: "DELETE FROM cycling.cyclist_name USING TIMESTAMP ? WHERE id=? ",
|
S: "DELETE FROM cycling.cyclist_name USING TIMESTAMP ? WHERE id=? ",
|
||||||
N: []string{"_ts", "expr"},
|
N: []string{"ts", "expr"},
|
||||||
},
|
},
|
||||||
// Add IF EXISTS
|
// Add IF EXISTS
|
||||||
{
|
{
|
||||||
@@ -68,7 +74,7 @@ func TestDeleteBuilder(t *testing.T) {
|
|||||||
t.Error(diff)
|
t.Error(diff)
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(test.N, names); diff != "" {
|
if diff := cmp.Diff(test.N, names); diff != "" {
|
||||||
t.Error(diff)
|
t.Error(diff, names)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
65
qb/expr.go
65
qb/expr.go
@@ -1,65 +0,0 @@
|
|||||||
// Copyright (C) 2017 ScyllaDB
|
|
||||||
// Use of this source code is governed by a ALv2-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package qb
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
)
|
|
||||||
|
|
||||||
type columns []string
|
|
||||||
|
|
||||||
func (cols columns) writeCql(cql *bytes.Buffer) {
|
|
||||||
for i, c := range cols {
|
|
||||||
cql.WriteString(c)
|
|
||||||
if i < len(cols)-1 {
|
|
||||||
cql.WriteByte(',')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type using struct {
|
|
||||||
timestamp bool
|
|
||||||
ttl bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u using) writeCql(cql *bytes.Buffer) (names []string) {
|
|
||||||
if u.timestamp {
|
|
||||||
cql.WriteString("USING TIMESTAMP ? ")
|
|
||||||
names = append(names, "_ts")
|
|
||||||
}
|
|
||||||
|
|
||||||
if u.ttl {
|
|
||||||
if u.timestamp {
|
|
||||||
cql.WriteString("AND TTL ? ")
|
|
||||||
} else {
|
|
||||||
cql.WriteString("USING TTL ? ")
|
|
||||||
}
|
|
||||||
names = append(names, "_ttl")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type where cmps
|
|
||||||
|
|
||||||
func (w where) writeCql(cql *bytes.Buffer) (names []string) {
|
|
||||||
if len(w) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cql.WriteString("WHERE ")
|
|
||||||
return cmps(w).writeCql(cql)
|
|
||||||
}
|
|
||||||
|
|
||||||
type _if cmps
|
|
||||||
|
|
||||||
func (w _if) writeCql(cql *bytes.Buffer) (names []string) {
|
|
||||||
if len(w) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cql.WriteString("IF ")
|
|
||||||
return cmps(w).writeCql(cql)
|
|
||||||
}
|
|
||||||
26
qb/insert.go
26
qb/insert.go
@@ -9,6 +9,7 @@ package qb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// initializer specifies an value for a column in an insert operation.
|
// initializer specifies an value for a column in an insert operation.
|
||||||
@@ -119,14 +120,27 @@ func (b *InsertBuilder) Unique() *InsertBuilder {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamp sets a USING TIMESTAMP clause on the query.
|
// TTL adds USING TTL clause to the query.
|
||||||
func (b *InsertBuilder) Timestamp() *InsertBuilder {
|
func (b *InsertBuilder) TTL(d time.Duration) *InsertBuilder {
|
||||||
b.using.timestamp = true
|
b.using.TTL(d)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// TTL sets a USING TTL clause on the query.
|
// TTLNamed adds USING TTL clause to the query with a custom parameter name.
|
||||||
func (b *InsertBuilder) TTL() *InsertBuilder {
|
func (b *InsertBuilder) TTLNamed(name string) *InsertBuilder {
|
||||||
b.using.ttl = true
|
b.using.TTLNamed(name)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timestamp adds USING TIMESTAMP clause to the query.
|
||||||
|
func (b *InsertBuilder) Timestamp(t time.Time) *InsertBuilder {
|
||||||
|
b.using.Timestamp(t)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampNamed adds a USING TIMESTAMP clause to the query with a custom
|
||||||
|
// parameter name.
|
||||||
|
func (b *InsertBuilder) TimestampNamed(name string) *InsertBuilder {
|
||||||
|
b.using.TimestampNamed(name)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package qb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
)
|
)
|
||||||
@@ -49,15 +50,25 @@ func TestInsertBuilder(t *testing.T) {
|
|||||||
},
|
},
|
||||||
// Add TTL
|
// Add TTL
|
||||||
{
|
{
|
||||||
B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").TTL(),
|
B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").TTL(time.Second),
|
||||||
|
S: "INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) USING TTL 1 ",
|
||||||
|
N: []string{"id", "user_uuid", "firstname"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").TTLNamed("ttl"),
|
||||||
S: "INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) USING TTL ? ",
|
S: "INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) USING TTL ? ",
|
||||||
N: []string{"id", "user_uuid", "firstname", "_ttl"},
|
N: []string{"id", "user_uuid", "firstname", "ttl"},
|
||||||
},
|
},
|
||||||
// Add TIMESTAMP
|
// Add TIMESTAMP
|
||||||
{
|
{
|
||||||
B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").Timestamp(),
|
B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)),
|
||||||
|
S: "INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) USING TIMESTAMP 1115251200000000 ",
|
||||||
|
N: []string{"id", "user_uuid", "firstname"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
B: Insert("cycling.cyclist_name").Columns("id", "user_uuid", "firstname").TimestampNamed("ts"),
|
||||||
S: "INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) USING TIMESTAMP ? ",
|
S: "INSERT INTO cycling.cyclist_name (id,user_uuid,firstname) VALUES (?,?,?) USING TIMESTAMP ? ",
|
||||||
N: []string{"id", "user_uuid", "firstname", "_ts"},
|
N: []string{"id", "user_uuid", "firstname", "ts"},
|
||||||
},
|
},
|
||||||
// Add IF NOT EXISTS
|
// Add IF NOT EXISTS
|
||||||
{
|
{
|
||||||
|
|||||||
26
qb/update.go
26
qb/update.go
@@ -9,6 +9,7 @@ package qb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// assignment specifies an assignment in a set operation.
|
// assignment specifies an assignment in a set operation.
|
||||||
@@ -78,15 +79,28 @@ func (b *UpdateBuilder) Table(table string) *UpdateBuilder {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamp sets a USING TIMESTAMP clause on the query.
|
// TTL adds USING TTL clause to the query.
|
||||||
func (b *UpdateBuilder) Timestamp() *UpdateBuilder {
|
func (b *UpdateBuilder) TTL(d time.Duration) *UpdateBuilder {
|
||||||
b.using.timestamp = true
|
b.using.TTL(d)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// TTL sets a USING TTL clause on the query.
|
// TTLNamed adds USING TTL clause to the query with a custom parameter name.
|
||||||
func (b *UpdateBuilder) TTL() *UpdateBuilder {
|
func (b *UpdateBuilder) TTLNamed(name string) *UpdateBuilder {
|
||||||
b.using.ttl = true
|
b.using.TTLNamed(name)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timestamp adds USING TIMESTAMP clause to the query.
|
||||||
|
func (b *UpdateBuilder) Timestamp(t time.Time) *UpdateBuilder {
|
||||||
|
b.using.Timestamp(t)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampNamed adds a USING TIMESTAMP clause to the query with a custom
|
||||||
|
// parameter name.
|
||||||
|
func (b *UpdateBuilder) TimestampNamed(name string) *UpdateBuilder {
|
||||||
|
b.using.TimestampNamed(name)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package qb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
)
|
)
|
||||||
@@ -98,15 +99,25 @@ func TestUpdateBuilder(t *testing.T) {
|
|||||||
},
|
},
|
||||||
// Add TTL
|
// Add TTL
|
||||||
{
|
{
|
||||||
B: Update("cycling.cyclist_name").Set("id", "user_uuid", "firstname").Where(w).TTL(),
|
B: Update("cycling.cyclist_name").Set("id", "user_uuid", "firstname").Where(w).TTL(time.Second),
|
||||||
|
S: "UPDATE cycling.cyclist_name USING TTL 1 SET id=?,user_uuid=?,firstname=? WHERE id=? ",
|
||||||
|
N: []string{"id", "user_uuid", "firstname", "expr"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
B: Update("cycling.cyclist_name").Set("id", "user_uuid", "firstname").Where(w).TTLNamed("ttl"),
|
||||||
S: "UPDATE cycling.cyclist_name USING TTL ? SET id=?,user_uuid=?,firstname=? WHERE id=? ",
|
S: "UPDATE cycling.cyclist_name USING TTL ? SET id=?,user_uuid=?,firstname=? WHERE id=? ",
|
||||||
N: []string{"_ttl", "id", "user_uuid", "firstname", "expr"},
|
N: []string{"ttl", "id", "user_uuid", "firstname", "expr"},
|
||||||
},
|
},
|
||||||
// Add TIMESTAMP
|
// Add TIMESTAMP
|
||||||
{
|
{
|
||||||
B: Update("cycling.cyclist_name").Set("id", "user_uuid", "firstname").Where(w).Timestamp(),
|
B: Update("cycling.cyclist_name").Set("id", "user_uuid", "firstname").Where(w).Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)),
|
||||||
|
S: "UPDATE cycling.cyclist_name USING TIMESTAMP 1115251200000000 SET id=?,user_uuid=?,firstname=? WHERE id=? ",
|
||||||
|
N: []string{"id", "user_uuid", "firstname", "expr"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
B: Update("cycling.cyclist_name").Set("id", "user_uuid", "firstname").Where(w).TimestampNamed("ts"),
|
||||||
S: "UPDATE cycling.cyclist_name USING TIMESTAMP ? SET id=?,user_uuid=?,firstname=? WHERE id=? ",
|
S: "UPDATE cycling.cyclist_name USING TIMESTAMP ? SET id=?,user_uuid=?,firstname=? WHERE id=? ",
|
||||||
N: []string{"_ts", "id", "user_uuid", "firstname", "expr"},
|
N: []string{"ts", "id", "user_uuid", "firstname", "expr"},
|
||||||
},
|
},
|
||||||
// Add IF EXISTS
|
// Add IF EXISTS
|
||||||
{
|
{
|
||||||
|
|||||||
92
qb/using.go
Normal file
92
qb/using.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
// Copyright (C) 2017 ScyllaDB
|
||||||
|
// Use of this source code is governed by a ALv2-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package qb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TTL converts duration to format expected in USING TTL clause.
|
||||||
|
func TTL(d time.Duration) int64 {
|
||||||
|
return int64(d.Seconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timestamp converts time to format expected in USING TIMESTAMP clause.
|
||||||
|
func Timestamp(t time.Time) int64 {
|
||||||
|
return t.UnixNano() / 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
type using struct {
|
||||||
|
ttl int64
|
||||||
|
ttlName string
|
||||||
|
timestamp int64
|
||||||
|
timestampName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *using) TTL(d time.Duration) *using {
|
||||||
|
u.ttl = TTL(d)
|
||||||
|
if u.ttl == 0 {
|
||||||
|
u.ttl = -1
|
||||||
|
}
|
||||||
|
u.timestampName = ""
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *using) TTLNamed(name string) *using {
|
||||||
|
u.ttl = 0
|
||||||
|
u.ttlName = name
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *using) Timestamp(t time.Time) *using {
|
||||||
|
u.timestamp = Timestamp(t)
|
||||||
|
u.timestampName = ""
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *using) TimestampNamed(name string) *using {
|
||||||
|
u.timestamp = 0
|
||||||
|
u.timestampName = name
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *using) writeCql(cql *bytes.Buffer) (names []string) {
|
||||||
|
hasTTL := false
|
||||||
|
|
||||||
|
if u.ttl != 0 {
|
||||||
|
hasTTL = true
|
||||||
|
if u.ttl == -1 {
|
||||||
|
u.ttl = 0
|
||||||
|
}
|
||||||
|
cql.WriteString("USING TTL ")
|
||||||
|
cql.WriteString(fmt.Sprint(u.ttl))
|
||||||
|
cql.WriteByte(' ')
|
||||||
|
} else if u.ttlName != "" {
|
||||||
|
hasTTL = true
|
||||||
|
cql.WriteString("USING TTL ? ")
|
||||||
|
names = append(names, u.ttlName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.timestamp != 0 {
|
||||||
|
if hasTTL {
|
||||||
|
cql.WriteString("AND TIMESTAMP ")
|
||||||
|
} else {
|
||||||
|
cql.WriteString("USING TIMESTAMP ")
|
||||||
|
}
|
||||||
|
cql.WriteString(fmt.Sprint(u.timestamp))
|
||||||
|
cql.WriteByte(' ')
|
||||||
|
} else if u.timestampName != "" {
|
||||||
|
if hasTTL {
|
||||||
|
cql.WriteString("AND TIMESTAMP ? ")
|
||||||
|
} else {
|
||||||
|
cql.WriteString("USING TIMESTAMP ? ")
|
||||||
|
}
|
||||||
|
names = append(names, u.timestampName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
102
qb/using_test.go
Normal file
102
qb/using_test.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
// Copyright (C) 2017 ScyllaDB
|
||||||
|
// Use of this source code is governed by a ALv2-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package qb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTTL(t *testing.T) {
|
||||||
|
if TTL(time.Second*86400) != 86400 {
|
||||||
|
t.Fatal("wrong ttl")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimestamp(t *testing.T) {
|
||||||
|
if Timestamp(time.Unix(0, 0).Add(time.Microsecond*123456789)) != 123456789 {
|
||||||
|
t.Fatal("wrong timestamp")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUsing(t *testing.T) {
|
||||||
|
table := []struct {
|
||||||
|
B *using
|
||||||
|
N []string
|
||||||
|
S string
|
||||||
|
}{
|
||||||
|
// TTL
|
||||||
|
{
|
||||||
|
B: new(using).TTL(time.Second),
|
||||||
|
S: "USING TTL 1 ",
|
||||||
|
},
|
||||||
|
// TTLNamed
|
||||||
|
{
|
||||||
|
B: new(using).TTLNamed("ttl"),
|
||||||
|
S: "USING TTL ? ",
|
||||||
|
N: []string{"ttl"},
|
||||||
|
},
|
||||||
|
// Timestamp
|
||||||
|
{
|
||||||
|
B: new(using).Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)),
|
||||||
|
S: "USING TIMESTAMP 1115251200000000 ",
|
||||||
|
},
|
||||||
|
// TimestampNamed
|
||||||
|
{
|
||||||
|
B: new(using).TimestampNamed("ts"),
|
||||||
|
S: "USING TIMESTAMP ? ",
|
||||||
|
N: []string{"ts"},
|
||||||
|
},
|
||||||
|
// TTL Timestamp
|
||||||
|
{
|
||||||
|
B: new(using).TTL(time.Second).Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)),
|
||||||
|
S: "USING TTL 1 AND TIMESTAMP 1115251200000000 ",
|
||||||
|
},
|
||||||
|
// TTLNamed TimestampNamed
|
||||||
|
{
|
||||||
|
B: new(using).TTLNamed("ttl").TimestampNamed("ts"),
|
||||||
|
S: "USING TTL ? AND TIMESTAMP ? ",
|
||||||
|
N: []string{"ttl", "ts"},
|
||||||
|
},
|
||||||
|
// TTL TTLNamed
|
||||||
|
{
|
||||||
|
B: new(using).TTL(time.Second).TTLNamed("ttl"),
|
||||||
|
S: "USING TTL ? ",
|
||||||
|
N: []string{"ttl"},
|
||||||
|
},
|
||||||
|
// TTLNamed TTL
|
||||||
|
{
|
||||||
|
B: new(using).TTLNamed("ttl").TTL(time.Second),
|
||||||
|
S: "USING TTL 1 ",
|
||||||
|
},
|
||||||
|
// Timestamp TimestampNamed
|
||||||
|
{
|
||||||
|
B: new(using).Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)).TimestampNamed("ts"),
|
||||||
|
S: "USING TIMESTAMP ? ",
|
||||||
|
N: []string{"ts"},
|
||||||
|
},
|
||||||
|
// TimestampNamed Timestamp
|
||||||
|
{
|
||||||
|
B: new(using).TimestampNamed("ts").Timestamp(time.Date(2005, 05, 05, 0, 0, 0, 0, time.UTC)),
|
||||||
|
S: "USING TIMESTAMP 1115251200000000 ",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range table {
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
names := test.B.writeCql(buf)
|
||||||
|
stmt := buf.String()
|
||||||
|
|
||||||
|
if diff := cmp.Diff(test.S, stmt); diff != "" {
|
||||||
|
t.Error(diff)
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(test.N, names); diff != "" {
|
||||||
|
t.Error(diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
qb/utils.go
16
qb/utils.go
@@ -6,7 +6,6 @@ package qb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// placeholders returns a string with count ? placeholders joined with commas.
|
// placeholders returns a string with count ? placeholders joined with commas.
|
||||||
@@ -22,12 +21,13 @@ func placeholders(cql *bytes.Buffer, count int) {
|
|||||||
cql.WriteByte('?')
|
cql.WriteByte('?')
|
||||||
}
|
}
|
||||||
|
|
||||||
// TTL converts duration to format expected in USING TTL clause.
|
type columns []string
|
||||||
func TTL(d time.Duration) int64 {
|
|
||||||
return int64(d.Seconds())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timestamp converts time to format expected in USING TIMESTAMP clause.
|
func (cols columns) writeCql(cql *bytes.Buffer) {
|
||||||
func Timestamp(t time.Time) int64 {
|
for i, c := range cols {
|
||||||
return t.UnixNano() / 1000
|
cql.WriteString(c)
|
||||||
|
if i < len(cols)-1 {
|
||||||
|
cql.WriteByte(',')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
// Copyright (C) 2017 ScyllaDB
|
|
||||||
// Use of this source code is governed by a ALv2-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package qb
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTTL(t *testing.T) {
|
|
||||||
if TTL(time.Second*86400) != 86400 {
|
|
||||||
t.Fatal("wrong ttl")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestamp(t *testing.T) {
|
|
||||||
if Timestamp(time.Unix(0, 0).Add(time.Microsecond*123456789)) != 123456789 {
|
|
||||||
t.Fatal("wrong timestamp")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user