Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(prettyCQL): prettyCQL crashes on ouf-of-bound access #433

Merged
merged 8 commits into from
Nov 12, 2024
18 changes: 9 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ require (
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed
github.com/mitchellh/mapstructure v1.5.0
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.20.0
github.com/prometheus/client_golang v1.20.5
github.com/scylladb/go-set v1.0.2
github.com/scylladb/gocqlx/v2 v2.8.0
github.com/spf13/cobra v1.8.1
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa
golang.org/x/net v0.28.0
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
golang.org/x/net v0.30.0
golang.org/x/sync v0.8.0
gonum.org/v1/gonum v0.15.1
gopkg.in/inf.v0 v0.9.1
Expand All @@ -25,21 +25,21 @@ require (
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/fatih/color v1.17.0 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/common v0.60.1 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/scylladb/go-reflectx v1.0.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sys v0.24.0 // indirect
golang.org/x/term v0.23.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/term v0.25.0 // indirect
google.golang.org/protobuf v1.35.1 // indirect
)

replace github.com/gocql/gocql => github.com/scylladb/gocql v1.14.3
18 changes: 18 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA=
github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
Expand All @@ -31,6 +33,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
Expand All @@ -55,12 +59,16 @@ github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQ
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI=
github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8=
github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc=
github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
Expand Down Expand Up @@ -94,11 +102,15 @@ golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 h1:LoYXNGAShUG3m/ehNk4iFctuh
golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
golang.org/x/net v0.0.0-20220526153639-5463443f8c37/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
Expand All @@ -111,11 +123,15 @@ golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand All @@ -127,6 +143,8 @@ google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFW
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
Expand Down
21 changes: 14 additions & 7 deletions pkg/typedef/bag.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,27 @@ func (ct *BagType) CQLHolder() string {
return "?"
}

func (ct *BagType) CQLPretty(value any) string {
func (ct *BagType) CQLPretty(builder *strings.Builder, value any) {
if reflect.TypeOf(value).Kind() != reflect.Slice {
panic(fmt.Sprintf("set cql pretty, unknown type %v", ct))
}
s := reflect.ValueOf(value)
format := "[%s]"

if ct.ComplexType == TYPE_SET {
format = "{%s}"
builder.WriteRune('{')
defer builder.WriteRune('}')
} else {
builder.WriteRune('[')
defer builder.WriteRune(']')
}
out := make([]string, s.Len())

s := reflect.ValueOf(value)

for i := 0; i < s.Len(); i++ {
out[i] = ct.ValueType.CQLPretty(s.Index(i).Interface())
ct.ValueType.CQLPretty(builder, s.Index(i).Interface())
if i < s.Len()-1 {
builder.WriteRune(',')
}
}
return fmt.Sprintf(format, strings.Join(out, ","))
}

func (ct *BagType) GenValue(r *rand.Rand, p *PartitionRangeConfig) []any {
Expand Down
4 changes: 3 additions & 1 deletion pkg/typedef/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package typedef

import (
"strings"

"github.com/gocql/gocql"
"golang.org/x/exp/rand"
)
Expand All @@ -23,7 +25,7 @@ type Type interface {
Name() string
CQLDef() string
CQLHolder() string
CQLPretty(any) string
CQLPretty(*strings.Builder, any)
GenValue(*rand.Rand, *PartitionRangeConfig) []any
GenJSONValue(*rand.Rand, *PartitionRangeConfig) any
LenValue() int
Expand Down
96 changes: 84 additions & 12 deletions pkg/typedef/simple_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"math"
"math/big"
"net"
"strconv"
"strings"
"time"

"github.com/gocql/gocql"
Expand Down Expand Up @@ -66,50 +68,120 @@ func (st SimpleType) LenValue() int {
return 1
}

func (st SimpleType) CQLPretty(value any) string {
func (st SimpleType) CQLPretty(builder *strings.Builder, value any) {
switch st {
case TYPE_ASCII, TYPE_TEXT, TYPE_VARCHAR, TYPE_INET, TYPE_DATE:
return fmt.Sprintf("'%s'", value)
case TYPE_INET:
builder.WriteRune('\'')
defer builder.WriteRune('\'')
switch v := value.(type) {
case net.IP:
builder.WriteString(v.String())
case net.IPMask:
builder.WriteString(v.String())
case string:
builder.WriteString(v)
}
case TYPE_ASCII, TYPE_TEXT, TYPE_VARCHAR, TYPE_DATE:
builder.WriteRune('\'')
builder.WriteString(value.(string))
builder.WriteRune('\'')
case TYPE_BLOB:
if v, ok := value.(string); ok {
if len(v) > 100 {
v = v[:100]
}
return "textasblob('" + v + "')"
builder.WriteString("textasblob('")
builder.WriteString(v)
builder.WriteString("')")
return
}

panic(fmt.Sprintf("unexpected blob value [%T]%+v", value, value))
case TYPE_BIGINT, TYPE_INT, TYPE_SMALLINT, TYPE_TINYINT:
return fmt.Sprintf("%d", value)
var i int64
switch v := value.(type) {
case int8:
i = int64(v)
case int16:
i = int64(v)
case int32:
i = int64(v)
case int:
i = int64(v)
case int64:
i = v
case *big.Int:
builder.WriteString(v.Text(10))
return
default:
panic(fmt.Sprintf("unexpected int value [%T]%+v", value, value))
}
builder.WriteString(strconv.FormatInt(i, 10))
case TYPE_DECIMAL, TYPE_DOUBLE, TYPE_FLOAT:
return fmt.Sprintf("%.2f", value)
var f float64
switch v := value.(type) {
case float32:
f = float64(v)
case float64:
f = v
case *inf.Dec:
builder.WriteString(v.String())
return
default:
panic(fmt.Sprintf("unexpected float value [%T]%+v", value, value))
}
builder.WriteString(strconv.FormatFloat(f, 'f', 2, 64))
case TYPE_BOOLEAN:
if v, ok := value.(bool); ok {
return fmt.Sprintf("%t", v)
builder.WriteString(strconv.FormatBool(v))
return
}

panic(fmt.Sprintf("unexpected boolean value [%T]%+v", value, value))
case TYPE_TIME:
if v, ok := value.(int64); ok {
builder.WriteRune('\'')
// CQL supports only 3 digits microseconds:
// '10:10:55.83275+0000': marshaling error: Milliseconds length exceeds expected (5)"
return fmt.Sprintf("'%s'", time.Time{}.Add(time.Duration(v)).Format("15:04:05.999"))
builder.WriteString(time.Time{}.Add(time.Duration(v)).Format("15:04:05.999"))
builder.WriteRune('\'')
return
}

panic(fmt.Sprintf("unexpected time value [%T]%+v", value, value))
case TYPE_TIMESTAMP:
if v, ok := value.(int64); ok {
// CQL supports only 3 digits milliseconds:
// '1976-03-25T10:10:55.83275+0000': marshaling error: Milliseconds length exceeds expected (5)"
return time.UnixMilli(v).UTC().Format("'2006-01-02T15:04:05.999-0700'")
builder.WriteString(time.UnixMilli(v).UTC().Format("'2006-01-02T15:04:05.999-0700'"))
return
}

panic(fmt.Sprintf("unexpected timestamp value [%T]%+v", value, value))
case TYPE_DURATION, TYPE_TIMEUUID, TYPE_UUID:
return fmt.Sprintf("%s", value)
switch v := value.(type) {
case string:
builder.WriteString(v)
return
case time.Duration:
builder.WriteString(v.String())
return
case gocql.UUID:
builder.WriteString(v.String())
return
}

panic(fmt.Sprintf("unexpected (duration|timeuuid|uuid) value [%T]%+v", value, value))
case TYPE_VARINT:
if s, ok := value.(*big.Int); ok {
return fmt.Sprintf("%d", s.Int64())
builder.WriteString(s.Text(10))
return
}

panic(fmt.Sprintf("unexpected varint value [%T]%+v", value, value))
default:
panic(fmt.Sprintf("cql pretty: not supported type %s", st))
panic(fmt.Sprintf("cql pretty: not supported type %s [%T]%+v", st, value, value))

}
}

Expand Down
16 changes: 10 additions & 6 deletions pkg/typedef/tuple.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package typedef

import (
"fmt"
"strings"

"github.com/gocql/gocql"
Expand Down Expand Up @@ -55,16 +54,21 @@ func (t *TupleType) CQLHolder() string {
return "(" + strings.TrimRight(strings.Repeat("?,", len(t.ValueTypes)), ",") + ")"
}

func (t *TupleType) CQLPretty(value any) string {
func (t *TupleType) CQLPretty(builder *strings.Builder, value any) {
values, ok := value.([]any)
if !ok {
return "()"
builder.WriteString("()")
CodeLieutenant marked this conversation as resolved.
Show resolved Hide resolved
}
out := make([]string, len(values))

builder.WriteRune('(')
defer builder.WriteRune(')')
dkropachev marked this conversation as resolved.
Show resolved Hide resolved

for i, tp := range t.ValueTypes {
out[i] = tp.CQLPretty(values[i])
tp.CQLPretty(builder, values[i])
if i < len(values)-1 {
builder.WriteRune(',')
}
}
return fmt.Sprintf("(%s)", strings.Join(out, ","))
}

func (t *TupleType) Indexable() bool {
Expand Down
Loading
Loading