Skip to content

Commit

Permalink
fix(prettyCQL): bounds checks for prettyCQL
Browse files Browse the repository at this point in the history
Signed-off-by: Dusan Malusev <[email protected]>
  • Loading branch information
CodeLieutenant committed Nov 5, 2024
1 parent 4ef2409 commit 17014b1
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 36 deletions.
40 changes: 40 additions & 0 deletions pkg/jobs/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2024 ScyllaDB
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package jobs

import (
"fmt"

"github.com/scylladb/gemini/pkg/typedef"
)

type PrettyCQLError struct {
PrettyCQL error
Err error
Stmt *typedef.Stmt
}

func (e PrettyCQLError) Error() string {
query, _ := e.Stmt.Query.ToCql()
values := e.Stmt.Values.Copy()

return fmt.Sprintf(
"Failed to format CQL Statement: prettyCQL {Query(%s) Values(%+v) PrettyCQLError(%+v) Error(%+v)}",
query,
values,
e.PrettyCQL,
e.Err,
)
}
103 changes: 68 additions & 35 deletions pkg/jobs/jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,20 @@ package jobs
import (
"context"
"encoding/json"
"errors"
"fmt"
"time"

"github.com/scylladb/gemini/pkg/generators"
"github.com/scylladb/gemini/pkg/store"
"github.com/scylladb/gemini/pkg/typedef"
"github.com/pkg/errors"
"go.uber.org/zap"
"golang.org/x/exp/rand"
"golang.org/x/sync/errgroup"

"github.com/scylladb/gemini/pkg/generators"
"github.com/scylladb/gemini/pkg/joberror"
"github.com/scylladb/gemini/pkg/status"
"github.com/scylladb/gemini/pkg/stop"

"go.uber.org/zap"
"golang.org/x/exp/rand"
"golang.org/x/sync/errgroup"
"github.com/scylladb/gemini/pkg/store"
"github.com/scylladb/gemini/pkg/typedef"
)

const (
Expand Down Expand Up @@ -177,9 +176,15 @@ func mutationJob(
}
ind := r.Intn(1000000)
if ind%100000 == 0 {
_ = ddl(ctx, schema, schemaConfig, table, s, r, p, globalStatus, logger, verbose)
err := ddl(ctx, schema, schemaConfig, table, s, r, p, globalStatus, logger, verbose)
if err != nil {
return err
}
} else {
_ = mutation(ctx, schema, schemaConfig, table, s, r, p, g, globalStatus, true, logger)
err := mutation(ctx, schema, schemaConfig, table, s, r, p, g, globalStatus, true, logger)
if err != nil {
return err
}
}
if failFast && globalStatus.HasErrors() {
stopFlag.SetSoft(true)
Expand Down Expand Up @@ -240,16 +245,20 @@ func validationJob(
return nil
default:
query, prettyErr := stmt.PrettyCQL()
if prettyErr != nil {
return PrettyCQLError{
PrettyCQL: prettyErr,
Stmt: stmt,
Err: err,
}
}

globalStatus.AddReadError(&joberror.JobError{
Timestamp: time.Now(),
StmtType: stmt.QueryType.ToString(),
StmtType: stmt.QueryType.String(),
Message: "Validation failed: " + err.Error(),
Query: query,
})

if prettyErr != nil {
return prettyErr
}
}

if failFast && globalStatus.HasErrors() {
Expand Down Expand Up @@ -288,7 +297,11 @@ func warmupJob(
return nil
}
// Do we care about errors during warmup?
_ = mutation(ctx, schema, schemaConfig, table, s, r, p, g, globalStatus, false, logger)
err := mutation(ctx, schema, schemaConfig, table, s, r, p, g, globalStatus, false, logger)
if err != nil {
return err
}

if failFast && globalStatus.HasErrors() {
stopFlag.SetSoft(true)
return nil
Expand Down Expand Up @@ -324,20 +337,25 @@ func ddl(
globalStatus.WriteErrors.Add(1)
return err
}

if ddlStmts == nil {
if w := logger.Check(zap.DebugLevel, "no statement generated"); w != nil {
w.Write(zap.String("job", "ddl"))
}
return nil
}

for _, ddlStmt := range ddlStmts.List {
if w := logger.Check(zap.DebugLevel, "ddl statement"); w != nil {
prettyCQL, prettyCQLErr := ddlStmt.PrettyCQL()
if prettyCQLErr != nil {
logger.Error("Failed! DDL PrettyCQL failed", zap.Error(prettyCQLErr))
} else {
w.Write(zap.String("pretty_cql", prettyCQL))
return PrettyCQLError{
PrettyCQL: prettyCQLErr,
Stmt: ddlStmt,
}
}

w.Write(zap.String("pretty_cql", prettyCQL))
}

if err = s.Mutate(ctx, ddlStmt); err != nil {
Expand All @@ -346,17 +364,21 @@ func ddl(
}

prettyCQL, prettyCQLErr := ddlStmt.PrettyCQL()
if prettyCQLErr != nil {
return PrettyCQLError{
PrettyCQL: prettyCQLErr,
Stmt: ddlStmt,
Err: err,
}
}

globalStatus.AddWriteError(&joberror.JobError{
Timestamp: time.Now(),
StmtType: ddlStmts.QueryType.ToString(),
StmtType: ddlStmts.QueryType.String(),
Message: "DDL failed: " + err.Error(),
Query: prettyCQL,
})

if prettyCQLErr != nil {
logger.Error("Failed! DDL PrettyCQL failed", zap.Error(prettyCQLErr))
}

return err
}
globalStatus.WriteOps.Add(1)
Expand Down Expand Up @@ -398,28 +420,36 @@ func mutation(
if w := logger.Check(zap.DebugLevel, "mutation statement"); w != nil {
prettyCQL, prettyCQLErr := mutateStmt.PrettyCQL()
if prettyCQLErr != nil {
logger.Error("Failed! mutation PrettyCQL failed", zap.Error(prettyCQLErr))
} else {
w.Write(zap.String("pretty_cql", prettyCQL))
return PrettyCQLError{
PrettyCQL: prettyCQLErr,
Stmt: mutateStmt,
Err: err,
}
}

w.Write(zap.String("pretty_cql", prettyCQL))
}
if err = s.Mutate(ctx, mutateStmt); err != nil {
if errors.Is(err, context.Canceled) {
return nil
}

prettyCQL, prettyCQLErr := mutateStmt.PrettyCQL()
if prettyCQLErr != nil {
return PrettyCQLError{
PrettyCQL: prettyCQLErr,
Stmt: mutateStmt,
Err: err,
}
}

globalStatus.AddWriteError(&joberror.JobError{
Timestamp: time.Now(),
StmtType: mutateStmt.QueryType.ToString(),
StmtType: mutateStmt.QueryType.String(),
Message: "Mutation failed: " + err.Error(),
Query: prettyCQL,
})

if prettyCQLErr != nil {
logger.Error("Failed! DDL PrettyCQL failed", zap.Error(prettyCQLErr))
}

return err
}

Expand All @@ -440,10 +470,13 @@ func validation(
if w := logger.Check(zap.DebugLevel, "validation statement"); w != nil {
prettyCQL, prettyCQLErr := stmt.PrettyCQL()
if prettyCQLErr != nil {
logger.Error("Failed! validation PrettyCQL failed", zap.Error(prettyCQLErr))
} else {
w.Write(zap.String("pretty_cql", prettyCQL))
return PrettyCQLError{
PrettyCQL: prettyCQLErr,
Stmt: stmt,
}
}

w.Write(zap.String("pretty_cql", prettyCQL))
}

maxAttempts := 1
Expand Down
4 changes: 4 additions & 0 deletions pkg/typedef/tuple.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ func (t *TupleType) CQLPretty(builder *bytes.Buffer, value any) error {
return nil
}

if len(values) != len(t.ValueTypes) {
return errors.Errorf("expected %d values, got %d", len(t.ValueTypes), len(values))
}

for i, tp := range t.ValueTypes {
if err := tp.CQLPretty(builder, values[i]); err != nil {
return err
Expand Down
11 changes: 10 additions & 1 deletion pkg/typedef/typedef.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"
"strings"

"github.com/pkg/errors"
"github.com/scylladb/gocqlx/v2/qb"

"github.com/scylladb/gemini/pkg/replication"
Expand Down Expand Up @@ -118,7 +119,7 @@ func (s *Stmt) Clone() *Stmt {

type StatementType uint8

func (st StatementType) ToString() string {
func (st StatementType) String() string {
switch st {
case SelectStatementType:
return "SelectStatement"
Expand Down Expand Up @@ -224,6 +225,10 @@ func prettyCQL(builder *bytes.Buffer, q string, values Values, types []Type) err
return nil
}

if len(values) < len(types) {
return errors.Errorf("expected at least %d values, got %d", len(types), len(values))
}

var (
skip int
idx int
Expand All @@ -242,6 +247,10 @@ func prettyCQL(builder *bytes.Buffer, q string, values Values, types []Type) err

var value any

if i >= len(types) {
return errors.Errorf("there are more(%d) ? in the query than types(%d), invalid Query: %s", len(types), i, q)
}

switch tt := types[i].(type) {
case *TupleType:
skip = tt.LenValue()
Expand Down
2 changes: 2 additions & 0 deletions results/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!.gitignore

0 comments on commit 17014b1

Please sign in to comment.