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 Foreign key fuzzer to ignore rows affected #15841

Merged
merged 2 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions go/test/endtoend/utils/cmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func (mcmp *MySQLCompare) AssertMatchesAnyNoCompare(query string, expected ...st
// Both clients need to return an error. The error of Vitess must be matching the given expectation.
func (mcmp *MySQLCompare) AssertContainsError(query, expected string) {
mcmp.t.Helper()
_, err := mcmp.ExecAllowAndCompareError(query)
_, err := mcmp.ExecAllowAndCompareError(query, CompareOptions{})
require.Error(mcmp.t, err)
assert.Contains(mcmp.t, err.Error(), expected, "actual error: %s", err.Error())
}
Expand Down Expand Up @@ -211,7 +211,7 @@ func (mcmp *MySQLCompare) Exec(query string) *sqltypes.Result {

mysqlQr, err := mcmp.MySQLConn.ExecuteFetch(query, 1000, true)
require.NoError(mcmp.t, err, "[MySQL Error] for query: "+query)
compareVitessAndMySQLResults(mcmp.t, query, mcmp.VtConn, vtQr, mysqlQr, false)
compareVitessAndMySQLResults(mcmp.t, query, mcmp.VtConn, vtQr, mysqlQr, CompareOptions{})
return vtQr
}

Expand All @@ -238,7 +238,7 @@ func (mcmp *MySQLCompare) ExecWithColumnCompare(query string) *sqltypes.Result {

mysqlQr, err := mcmp.MySQLConn.ExecuteFetch(query, 1000, true)
require.NoError(mcmp.t, err, "[MySQL Error] for query: "+query)
compareVitessAndMySQLResults(mcmp.t, query, mcmp.VtConn, vtQr, mysqlQr, true)
compareVitessAndMySQLResults(mcmp.t, query, mcmp.VtConn, vtQr, mysqlQr, CompareOptions{CompareColumnNames: true})
return vtQr
}

Expand All @@ -250,7 +250,7 @@ func (mcmp *MySQLCompare) ExecWithColumnCompare(query string) *sqltypes.Result {
// The result set and error produced by Vitess are returned to the caller.
// If the Vitess and MySQL error are both nil, but the results do not match,
// the mismatched results are instead returned as an error, as well as the Vitess result set
func (mcmp *MySQLCompare) ExecAllowAndCompareError(query string) (*sqltypes.Result, error) {
func (mcmp *MySQLCompare) ExecAllowAndCompareError(query string, opts CompareOptions) (*sqltypes.Result, error) {
mcmp.t.Helper()
vtQr, vtErr := mcmp.VtConn.ExecuteFetch(query, 1000, true)
mysqlQr, mysqlErr := mcmp.MySQLConn.ExecuteFetch(query, 1000, true)
Expand All @@ -259,7 +259,7 @@ func (mcmp *MySQLCompare) ExecAllowAndCompareError(query string) (*sqltypes.Resu
// Since we allow errors, we don't want to compare results if one of the client failed.
// Vitess and MySQL should always be agreeing whether the query returns an error or not.
if vtErr == nil && mysqlErr == nil {
vtErr = compareVitessAndMySQLResults(mcmp.t, query, mcmp.VtConn, vtQr, mysqlQr, false)
vtErr = compareVitessAndMySQLResults(mcmp.t, query, mcmp.VtConn, vtQr, mysqlQr, opts)
}
return vtQr, vtErr
}
Expand Down Expand Up @@ -297,7 +297,7 @@ func (mcmp *MySQLCompare) ExecAllowError(query string) (*sqltypes.Result, error)
// Since we allow errors, we don't want to compare results if one of the client failed.
// Vitess and MySQL should always be agreeing whether the query returns an error or not.
if mysqlErr == nil {
vtErr = compareVitessAndMySQLResults(mcmp.t, query, mcmp.VtConn, vtQr, mysqlQr, false)
vtErr = compareVitessAndMySQLResults(mcmp.t, query, mcmp.VtConn, vtQr, mysqlQr, CompareOptions{})
}
return vtQr, vtErr
}
14 changes: 12 additions & 2 deletions go/test/endtoend/utils/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,12 @@ func prepareMySQLWithSchema(params mysql.ConnParams, sql string) error {
return nil
}

func compareVitessAndMySQLResults(t TestingT, query string, vtConn *mysql.Conn, vtQr, mysqlQr *sqltypes.Result, compareColumnNames bool) error {
type CompareOptions struct {
CompareColumnNames bool
IgnoreRowsAffected bool
}

func compareVitessAndMySQLResults(t TestingT, query string, vtConn *mysql.Conn, vtQr, mysqlQr *sqltypes.Result, opts CompareOptions) error {
t.Helper()

if vtQr == nil && mysqlQr == nil {
Expand Down Expand Up @@ -203,7 +208,7 @@ func compareVitessAndMySQLResults(t TestingT, query string, vtConn *mysql.Conn,
myCols = append(myCols, myField.Name)
}

if compareColumnNames && !assert.Equal(t, myCols, vtCols, "column names do not match - the expected values are what mysql produced") {
if opts.CompareColumnNames && !assert.Equal(t, myCols, vtCols, "column names do not match - the expected values are what mysql produced") {
t.Errorf("column names do not match - the expected values are what mysql produced\nNot equal: \nexpected: %v\nactual: %v\n", myCols, vtCols)
}
}
Expand All @@ -218,6 +223,11 @@ func compareVitessAndMySQLResults(t TestingT, query string, vtConn *mysql.Conn,
orderBy = selStmt.GetOrderBy() != nil
}

if opts.IgnoreRowsAffected {
vtQr.RowsAffected = 0
mysqlQr.RowsAffected = 0
}

if (orderBy && sqltypes.ResultsEqual([]sqltypes.Result{*vtQr}, []sqltypes.Result{*mysqlQr})) || sqltypes.ResultsEqualUnordered([]sqltypes.Result{*vtQr}, []sqltypes.Result{*mysqlQr}) {
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion go/test/endtoend/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func ExecCompareMySQL(t *testing.T, vtConn, mysqlConn *mysql.Conn, query string)

mysqlQr, err := mysqlConn.ExecuteFetch(query, 1000, true)
require.NoError(t, err, "[MySQL Error] for query: "+query)
compareVitessAndMySQLResults(t, query, vtConn, vtQr, mysqlQr, false)
compareVitessAndMySQLResults(t, query, vtConn, vtQr, mysqlQr, CompareOptions{})
return vtQr
}

Expand Down
2 changes: 1 addition & 1 deletion go/test/endtoend/vtgate/foreignkey/fk_fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ func (fz *fuzzer) generateAndExecuteStatementQuery(t *testing.T, mcmp utils.MySQ
for _, query := range queries {
// When the concurrency is 1, then we run the query both on MySQL and Vitess.
if fz.concurrency == 1 {
_, _ = mcmp.ExecAllowAndCompareError(query)
_, _ = mcmp.ExecAllowAndCompareError(query, utils.CompareOptions{IgnoreRowsAffected: true})
// If t is marked failed, we have encountered our first failure.
// Let's collect the required information and finish execution.
if t.Failed() {
Expand Down
22 changes: 17 additions & 5 deletions go/test/endtoend/vtgate/foreignkey/fk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ func TestFkScenarios(t *testing.T) {
}

// Run the DML query that needs to be tested and verify output with MySQL.
_, err := mcmp.ExecAllowAndCompareError(tt.dmlQuery)
_, err := mcmp.ExecAllowAndCompareError(tt.dmlQuery, utils.CompareOptions{})
if tt.dmlShouldErr {
assert.Error(t, err)
} else {
Expand Down Expand Up @@ -948,7 +948,7 @@ func TestFkScenarios(t *testing.T) {
mcmp.Exec("SELECT * FROM fk_t13 ORDER BY id")

// Update that fails
_, err := mcmp.ExecAllowAndCompareError("UPDATE fk_t10 SET col = 15 WHERE id = 1")
_, err := mcmp.ExecAllowAndCompareError("UPDATE fk_t10 SET col = 15 WHERE id = 1", utils.CompareOptions{})
require.Error(t, err)

// Verify the results
Expand Down Expand Up @@ -1006,6 +1006,7 @@ func TestFkQueries(t *testing.T) {
testcases := []struct {
name string
queries []string
opts utils.CompareOptions
}{
{
name: "Non-literal update",
Expand Down Expand Up @@ -1135,6 +1136,17 @@ func TestFkQueries(t *testing.T) {
"delete fk_t11 from fk_t11 join fk_t12 using (id) where fk_t11.id = 4",
},
},
{
name: "Multi table delete where MySQL and Vitess report different rows affected",
queries: []string{
"insert /*+ SET_VAR(foreign_key_checks=0) */ into fk_t11 (id, col) values (4, '1'), (5, '3'), (7, '22'), (8, '5'), (9, NULL), (10, '3')",
"insert /*+ SET_VAR(foreign_key_checks=0) */ into fk_t12 (id, col) values (4, '1'), (5, '3'), (7, '22'), (8, '5'), (9, NULL), (10, '3')",
"delete fk_t11, fk_t12 from fk_t11 join fk_t12 using (id) where fk_t11.id = 5",
},
opts: utils.CompareOptions{
IgnoreRowsAffected: true,
},
},
}

for _, tt := range testcases {
Expand All @@ -1153,7 +1165,7 @@ func TestFkQueries(t *testing.T) {
ensureDatabaseState(t, mcmp.MySQLConn, true)

for _, query := range tt.queries {
_, _ = mcmp.ExecAllowAndCompareError(query)
_, _ = mcmp.ExecAllowAndCompareError(query, tt.opts)
if t.Failed() {
break
}
Expand Down Expand Up @@ -1212,7 +1224,7 @@ func TestFkOneCase(t *testing.T) {
log.Errorf("Query %v, Result - %v", query, res.Rows)
continue
}
_, _ = mcmp.ExecAllowAndCompareError(query)
_, _ = mcmp.ExecAllowAndCompareError(query, utils.CompareOptions{})
if t.Failed() {
log.Errorf("Query failed - %v", query)
break
Expand Down Expand Up @@ -1490,5 +1502,5 @@ create table temp2(id bigint auto_increment primary key, col varchar(20) not nul
mcmp.Exec(`set foreign_key_checks = on`)
mcmp.Exec(`insert into temp2(col) values('a'), ('b'), ('c') `)
mcmp.Exec(`insert into temp1(col) values('a') `)
mcmp.ExecAllowAndCompareError(`insert into temp1(col) values('d') `)
mcmp.ExecAllowAndCompareError(`insert into temp1(col) values('d') `, utils.CompareOptions{})
}
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ func TestHavingQueries(t *testing.T) {

for _, query := range queries {
mcmp.Run(query, func(mcmp *utils.MySQLCompare) {
mcmp.ExecAllowAndCompareError(query)
mcmp.ExecAllowAndCompareError(query, utils.CompareOptions{})
})
}
}
2 changes: 1 addition & 1 deletion go/test/endtoend/vtgate/queries/dml/dml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ func TestDeleteWithSubquery(t *testing.T) {
`[[INT64(1) INT64(1) INT64(4)] [INT64(1) INT64(2) INT64(2)] [INT64(2) INT64(3) INT64(5)]]`)

// delete with subquery from same table (fails on mysql) - subquery get's merged so fails for vitess
_, err := mcmp.ExecAllowAndCompareError(`delete from s_tbl where id in (select id from s_tbl)`)
_, err := mcmp.ExecAllowAndCompareError(`delete from s_tbl where id in (select id from s_tbl)`, utils.CompareOptions{})
require.ErrorContains(t, err, "You can't specify target table 's_tbl' for update in FROM clause (errno 1093) (sqlstate HY000)")

// delete with subquery from same table (fails on mysql) - subquery not merged so passes for vitess
Expand Down
16 changes: 8 additions & 8 deletions go/test/endtoend/vtgate/queries/misc/misc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ func TestInvalidDateTimeTimestampVals(t *testing.T) {
mcmp, closer := start(t)
defer closer()

_, err := mcmp.ExecAllowAndCompareError(`select date'2022'`)
_, err := mcmp.ExecAllowAndCompareError(`select date'2022'`, utils.CompareOptions{})
require.Error(t, err)
_, err = mcmp.ExecAllowAndCompareError(`select time'12:34:56:78'`)
_, err = mcmp.ExecAllowAndCompareError(`select time'12:34:56:78'`, utils.CompareOptions{})
require.Error(t, err)
_, err = mcmp.ExecAllowAndCompareError(`select timestamp'2022'`)
_, err = mcmp.ExecAllowAndCompareError(`select timestamp'2022'`, utils.CompareOptions{})
require.Error(t, err)
}

Expand Down Expand Up @@ -257,12 +257,12 @@ func TestPrepareStatements(t *testing.T) {
mcmp.AssertMatchesNoOrder(`execute prep_in_pk using @id1, @id2`, `[[INT64(0) INT64(0)] [INT64(1) INT64(0)]]`)

// Fail by providing wrong number of arguments
_, err := mcmp.ExecAllowAndCompareError(`execute prep_in_pk using @id1, @id1, @id`)
_, err := mcmp.ExecAllowAndCompareError(`execute prep_in_pk using @id1, @id1, @id`, utils.CompareOptions{})
incorrectCount := "VT03025: Incorrect arguments to EXECUTE"
assert.ErrorContains(t, err, incorrectCount)
_, err = mcmp.ExecAllowAndCompareError(`execute prep_in_pk using @id1`)
_, err = mcmp.ExecAllowAndCompareError(`execute prep_in_pk using @id1`, utils.CompareOptions{})
assert.ErrorContains(t, err, incorrectCount)
_, err = mcmp.ExecAllowAndCompareError(`execute prep_in_pk`)
_, err = mcmp.ExecAllowAndCompareError(`execute prep_in_pk`, utils.CompareOptions{})
assert.ErrorContains(t, err, incorrectCount)

mcmp.Exec(`prepare prep_art from 'select 1+?, 10/?'`)
Expand All @@ -282,10 +282,10 @@ func TestPrepareStatements(t *testing.T) {
mcmp.Exec(`select 1+9999999999999999999999999999, 10/9999999999999999999999999999 from t1 limit 1`)

mcmp.Exec("deallocate prepare prep_art")
_, err = mcmp.ExecAllowAndCompareError(`execute prep_art using @id1, @id1`)
_, err = mcmp.ExecAllowAndCompareError(`execute prep_art using @id1, @id1`, utils.CompareOptions{})
assert.ErrorContains(t, err, "VT09011: Unknown prepared statement handler (prep_art) given to EXECUTE")

_, err = mcmp.ExecAllowAndCompareError("deallocate prepare prep_art")
_, err = mcmp.ExecAllowAndCompareError("deallocate prepare prep_art", utils.CompareOptions{})
assert.ErrorContains(t, err, "VT09011: Unknown prepared statement handler (prep_art) given to DEALLOCATE PREPARE")
}

Expand Down
2 changes: 1 addition & 1 deletion go/test/endtoend/vtgate/queries/orderby/orderby_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func TestOrderByComplex(t *testing.T) {

for _, query := range queries {
mcmp.Run(query, func(mcmp *utils.MySQLCompare) {
_, _ = mcmp.ExecAllowAndCompareError(query)
_, _ = mcmp.ExecAllowAndCompareError(query, utils.CompareOptions{})
})
}
}
4 changes: 2 additions & 2 deletions go/test/endtoend/vtgate/queries/random/random_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func helperTest(t *testing.T, query string) {
mcmp, closer := start(t)
defer closer()

result, err := mcmp.ExecAllowAndCompareError(query)
result, err := mcmp.ExecAllowAndCompareError(query, utils.CompareOptions{})
fmt.Println(result)
fmt.Println(err)
})
Expand Down Expand Up @@ -261,7 +261,7 @@ func TestRandom(t *testing.T) {
qg := newQueryGenerator(genConfig, 2, 2, 2, schemaTables)
qg.randomQuery()
query := sqlparser.String(qg.stmt)
_, vtErr := mcmp.ExecAllowAndCompareError(query)
_, vtErr := mcmp.ExecAllowAndCompareError(query, utils.CompareOptions{})

// this assumes all queries are valid mysql queries
if vtErr != nil {
Expand Down
6 changes: 3 additions & 3 deletions go/test/endtoend/vtgate/queries/random/simplifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestSimplifyResultsMismatchedQuery(t *testing.T) {
mcmp, closer := start(t)
defer closer()

mcmp.ExecAllowAndCompareError(simplified)
mcmp.ExecAllowAndCompareError(simplified, utils.CompareOptions{})
})

fmt.Printf("final simplified query: %s\n", simplified)
Expand All @@ -77,7 +77,7 @@ func simplifyResultsMismatchedQuery(t *testing.T, query string) string {
mcmp, closer := start(t)
defer closer()

_, err := mcmp.ExecAllowAndCompareError(query)
_, err := mcmp.ExecAllowAndCompareError(query, utils.CompareOptions{})
if err == nil {
t.Fatalf("query (%s) does not error", query)
} else if !strings.Contains(err.Error(), "mismatched") {
Expand Down Expand Up @@ -105,7 +105,7 @@ func simplifyResultsMismatchedQuery(t *testing.T, query string) string {
vSchemaWrapper,
func(statement sqlparser.SelectStatement) bool {
q := sqlparser.String(statement)
_, newErr := mcmp.ExecAllowAndCompareError(q)
_, newErr := mcmp.ExecAllowAndCompareError(q, utils.CompareOptions{})
if newErr == nil {
return false
} else {
Expand Down
Loading