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

Update Planning for Limits in the presence of foreign keys #15372

Merged
merged 7 commits into from
Mar 6, 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
22 changes: 18 additions & 4 deletions go/test/endtoend/vtgate/foreignkey/fk_fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,15 @@ func (fz *fuzzer) generateUpdateDMLQuery() string {
idValue := 1 + rand.Intn(fz.maxValForId)
tableName := fkTables[tableId]
setVarFkChecksVal := fz.getSetVarFkChecksVal()
updWithLimit := rand.Intn(2)
limitCount := rand.Intn(3)
if tableName == "fk_t20" {
colValue := convertIntValueToString(rand.Intn(1 + fz.maxValForCol))
col2Value := convertIntValueToString(rand.Intn(1 + fz.maxValForCol))
return fmt.Sprintf("update %v%v set col = %v, col2 = %v where id = %v", setVarFkChecksVal, tableName, colValue, col2Value, idValue)
if updWithLimit == 0 {
return fmt.Sprintf("update %v%v set col = %v, col2 = %v where id = %v", setVarFkChecksVal, tableName, colValue, col2Value, idValue)
}
return fmt.Sprintf("update %v%v set col = %v, col2 = %v order by id limit %v", setVarFkChecksVal, tableName, colValue, col2Value, limitCount)
} else if isMultiColFkTable(tableName) {
if rand.Intn(2) == 0 {
colaValue := convertIntValueToString(rand.Intn(1 + fz.maxValForCol))
Expand All @@ -169,15 +174,24 @@ func (fz *fuzzer) generateUpdateDMLQuery() string {
colaValue = fz.generateExpression(rand.Intn(4)+1, "cola", "colb", "id")
colbValue = fz.generateExpression(rand.Intn(4)+1, "cola", "colb", "id")
}
return fmt.Sprintf("update %v%v set cola = %v, colb = %v where id = %v", setVarFkChecksVal, tableName, colaValue, colbValue, idValue)
if updWithLimit == 0 {
return fmt.Sprintf("update %v%v set cola = %v, colb = %v where id = %v", setVarFkChecksVal, tableName, colaValue, colbValue, idValue)
}
return fmt.Sprintf("update %v%v set cola = %v, colb = %v order by id limit %v", setVarFkChecksVal, tableName, colaValue, colbValue, limitCount)
} else {
colValue := fz.generateExpression(rand.Intn(4)+1, "cola", "colb", "id")
colToUpdate := []string{"cola", "colb"}[rand.Intn(2)]
return fmt.Sprintf("update %v set %v = %v where id = %v", tableName, colToUpdate, colValue, idValue)
if updWithLimit == 0 {
return fmt.Sprintf("update %v set %v = %v where id = %v", tableName, colToUpdate, colValue, idValue)
}
return fmt.Sprintf("update %v set %v = %v order by id limit %v", tableName, colToUpdate, colValue, limitCount)
}
} else {
colValue := fz.generateExpression(rand.Intn(4)+1, "col", "id")
return fmt.Sprintf("update %v%v set col = %v where id = %v", setVarFkChecksVal, tableName, colValue, idValue)
if updWithLimit == 0 {
return fmt.Sprintf("update %v%v set col = %v where id = %v", setVarFkChecksVal, tableName, colValue, idValue)
}
return fmt.Sprintf("update %v%v set col = %v order by id limit %v", setVarFkChecksVal, tableName, colValue, limitCount)
}
}

Expand Down
217 changes: 153 additions & 64 deletions go/test/endtoend/vtgate/foreignkey/fk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,14 +379,16 @@ func TestFkScenarios(t *testing.T) {
name string
dataQueries []string
dmlQuery string
dmlShouldErr bool
assertionQueries []string
}{
{
name: "Insert failure due to parent key not existing",
dataQueries: []string{
"insert into fk_t1(id, col) values (1, 5)",
},
dmlQuery: "insert into t2(id, col) values (1, 7)",
dmlQuery: "insert into t2(id, col) values (1, 7)",
dmlShouldErr: true,
assertionQueries: []string{
"select * from fk_t1 order by id",
"select * from fk_t2 order by id",
Expand All @@ -407,7 +409,8 @@ func TestFkScenarios(t *testing.T) {
"insert into fk_t1(id, col) values (1, 7)",
"insert into fk_t2(id, col) values (1, 7)",
},
dmlQuery: "update fk_t1 set col = 5 where id = 1",
dmlShouldErr: true,
dmlQuery: "update fk_t1 set col = 5 where id = 1",
assertionQueries: []string{
"select * from fk_t1 order by id",
"select * from fk_t2 order by id",
Expand All @@ -429,7 +432,8 @@ func TestFkScenarios(t *testing.T) {
"insert into fk_t1(id, col) values (1, 7)",
"insert into fk_t2(id, col) values (1, 7)",
},
dmlQuery: "delete from fk_t1 where id = 1",
dmlQuery: "delete from fk_t1 where id = 1",
dmlShouldErr: true,
assertionQueries: []string{
"select * from fk_t1 order by id",
"select * from fk_t2 order by id",
Expand All @@ -450,7 +454,7 @@ func TestFkScenarios(t *testing.T) {
dataQueries: []string{
"insert into fk_t1(id, col) values (1, 7), (2, 9)",
"insert into fk_t2(id, col) values (1, 7), (2, 9)",
"insert into fk_t3(id, col) values (1, 7), (2, 9)",
"insert into fk_t3(id, col) values (1, 7)",
"insert into fk_t6(id, col) values (1, 7)",
},
dmlQuery: "update fk_t3 set col = 9 where id = 1",
Expand All @@ -469,7 +473,8 @@ func TestFkScenarios(t *testing.T) {
"insert into fk_t4(id, col) values (1, 7)",
"insert into fk_t5(id, col) values (1, 7)",
},
dmlQuery: "update fk_t3 set col = 9 where id = 1",
dmlQuery: "update fk_t3 set col = 9 where id = 1",
dmlShouldErr: true,
assertionQueries: []string{
"select * from fk_t1 order by id",
"select * from fk_t2 order by id",
Expand Down Expand Up @@ -518,7 +523,8 @@ func TestFkScenarios(t *testing.T) {
"insert into fk_t4(id, col) values (1, 7)",
"insert into fk_t5(id, col) values (1, 7)",
},
dmlQuery: "delete from fk_t3 where id = 1",
dmlQuery: "delete from fk_t3 where id = 1",
dmlShouldErr: true,
assertionQueries: []string{
"select * from fk_t1 order by id",
"select * from fk_t2 order by id",
Expand Down Expand Up @@ -561,7 +567,8 @@ func TestFkScenarios(t *testing.T) {
"insert into fk_t11(id, col) values (1, 7)",
"insert into fk_t13(id, col) values (1, 7)",
},
dmlQuery: "update fk_t10 set col = 5 where id = 1",
dmlQuery: "update fk_t10 set col = 5 where id = 1",
dmlShouldErr: true,
assertionQueries: []string{
"select * from fk_t10 order by id",
"select * from fk_t11 order by id",
Expand Down Expand Up @@ -598,7 +605,8 @@ func TestFkScenarios(t *testing.T) {
"insert into fk_t11(id, col) values (1, 7)",
"insert into fk_t13(id, col) values (1, 7)",
},
dmlQuery: "delete from fk_t10 where id = 1",
dmlQuery: "delete from fk_t10 where id = 1",
dmlShouldErr: true,
assertionQueries: []string{
"select * from fk_t10 order by id",
"select * from fk_t11 order by id",
Expand All @@ -620,47 +628,47 @@ func TestFkScenarios(t *testing.T) {
}, {
name: "Delete success with set null to an update cascade foreign key",
dataQueries: []string{
"insert into fk_t15(id, col) values (1, 7), (2, 9)",
"insert into fk_t16(id, col) values (1, 7), (2, 9)",
"insert into fk_t17(id, col) values (1, 7)",
"insert into fk_t18(id, col) values (1, 7)",
"insert into fk_multicol_t15(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t16(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t17(id, cola, colb) values (1, 7, 1)",
"insert into fk_multicol_t18(id, cola, colb) values (1, 7, 1)",
},
dmlQuery: "delete from fk_t16 where id = 1",
dmlQuery: "delete from fk_multicol_t16 where id = 1",
assertionQueries: []string{
"select * from fk_t15 order by id",
"select * from fk_t16 order by id",
"select * from fk_t17 order by id",
"select * from fk_t18 order by id",
"select * from fk_multicol_t15 order by id",
"select * from fk_multicol_t16 order by id",
"select * from fk_multicol_t17 order by id",
"select * from fk_multicol_t18 order by id",
},
}, {
name: "Delete success with cascade to delete with set null to an update set null foreign key",
dataQueries: []string{
"insert into fk_t15(id, col) values (1, 7), (2, 9)",
"insert into fk_t16(id, col) values (1, 7), (2, 9)",
"insert into fk_t17(id, col) values (1, 7)",
"insert into fk_t19(id, col) values (1, 7)",
"insert into fk_multicol_t15(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t16(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t17(id, cola, colb) values (1, 7, 1)",
"insert into fk_multicol_t18(id, cola, colb) values (1, 7, 1)",
},
dmlQuery: "delete from fk_t15 where id = 1",
dmlQuery: "delete from fk_multicol_t15 where id = 1",
assertionQueries: []string{
"select * from fk_t15 order by id",
"select * from fk_t16 order by id",
"select * from fk_t17 order by id",
"select * from fk_t19 order by id",
"select * from fk_multicol_t15 order by id",
"select * from fk_multicol_t16 order by id",
"select * from fk_multicol_t17 order by id",
"select * from fk_multicol_t18 order by id",
},
}, {
name: "Update success with cascade to an update set null to an update cascade foreign key",
dataQueries: []string{
"insert into fk_t15(id, col) values (1, 7), (2, 9)",
"insert into fk_t16(id, col) values (1, 7), (2, 9)",
"insert into fk_t17(id, col) values (1, 7)",
"insert into fk_t18(id, col) values (1, 7)",
"insert into fk_multicol_t15(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t16(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t17(id, cola, colb) values (1, 7, 1)",
"insert into fk_multicol_t18(id, cola, colb) values (1, 7, 1)",
},
dmlQuery: "update fk_t15 set col = 3 where id = 1",
dmlQuery: "update fk_multicol_t15 set cola = 3 where id = 1",
assertionQueries: []string{
"select * from fk_t15 order by id",
"select * from fk_t16 order by id",
"select * from fk_t17 order by id",
"select * from fk_t18 order by id",
"select * from fk_multicol_t15 order by id",
"select * from fk_multicol_t16 order by id",
"select * from fk_multicol_t17 order by id",
"select * from fk_multicol_t18 order by id",
},
}, {
name: "Insert success for self-referenced foreign key",
Expand All @@ -676,54 +684,130 @@ func TestFkScenarios(t *testing.T) {
dataQueries: []string{
"insert into fk_t20(id, col, col2) values (5, 7, NULL)",
},
dmlQuery: "insert into fk_t20(id, col, col2) values (6, 9, 6)",
dmlQuery: "insert into fk_t20(id, col, col2) values (6, 9, 6)",
dmlShouldErr: true,
assertionQueries: []string{
"select * from fk_t20 order by id",
},
}, {
name: "Multi Table Delete success",
dataQueries: []string{
"insert into fk_t15(id, col) values (1, 7), (2, 9)",
"insert into fk_t16(id, col) values (1, 7), (2, 9)",
"insert into fk_t17(id, col) values (1, 7)",
"insert into fk_t19(id, col) values (1, 7)",
"insert into fk_multicol_t15(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t16(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t17(id, cola, colb) values (1, 7, 1)",
"insert into fk_multicol_t19(id, cola, colb) values (1, 7, 1)",
},
dmlQuery: "delete fk_t15 from fk_t15 join fk_t17 using id",
dmlQuery: "delete fk_multicol_t15 from fk_multicol_t15 join fk_multicol_t17 where fk_multicol_t15.id = fk_multicol_t17.id",
assertionQueries: []string{
"select * from fk_t15 order by id",
"select * from fk_t16 order by id",
"select * from fk_t17 order by id",
"select * from fk_t19 order by id",
"select * from fk_multicol_t15 order by id",
"select * from fk_multicol_t16 order by id",
"select * from fk_multicol_t17 order by id",
"select * from fk_multicol_t19 order by id",
},
}, {
name: "Delete with limit success",
dataQueries: []string{
"insert into fk_t15(id, col) values (1, 7), (2, 9)",
"insert into fk_t16(id, col) values (1, 7), (2, 9)",
"insert into fk_t17(id, col) values (1, 7)",
"insert into fk_t19(id, col) values (1, 7)",
"insert into fk_multicol_t15(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t16(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t17(id, cola, colb) values (1, 7, 1)",
"insert into fk_multicol_t19(id, cola, colb) values (1, 7, 1)",
},
dmlQuery: "delete from fk_t15 order by id limit 1",
dmlQuery: "delete from fk_multicol_t15 order by id limit 1",
assertionQueries: []string{
"select * from fk_t15 order by id",
"select * from fk_t16 order by id",
"select * from fk_t17 order by id",
"select * from fk_t19 order by id",
"select * from fk_multicol_t15 order by id",
"select * from fk_multicol_t16 order by id",
"select * from fk_multicol_t17 order by id",
"select * from fk_multicol_t19 order by id",
},
}, {
name: "Delete with limit 0 success",
dataQueries: []string{
"insert into fk_t15(id, col) values (1, 7), (2, 9)",
"insert into fk_t16(id, col) values (1, 7), (2, 9)",
"insert into fk_t17(id, col) values (1, 7)",
"insert into fk_t19(id, col) values (1, 7)",
"insert into fk_multicol_t15(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t16(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t17(id, cola, colb) values (1, 7, 1)",
"insert into fk_multicol_t19(id, cola, colb) values (1, 7, 1)",
},
dmlQuery: "delete from fk_multicol_t15 order by id limit 0",
assertionQueries: []string{
"select * from fk_multicol_t15 order by id",
"select * from fk_multicol_t16 order by id",
"select * from fk_multicol_t17 order by id",
"select * from fk_multicol_t19 order by id",
},
}, {
name: "Update with limit success",
dataQueries: []string{
"insert into fk_multicol_t15(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t16(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t17(id, cola, colb) values (1, 7, 1)",
"insert into fk_multicol_t19(id, cola, colb) values (1, 7, 1)",
},
dmlQuery: "update fk_multicol_t15 set cola = '2' order by id limit 1",
assertionQueries: []string{
"select * from fk_multicol_t15 order by id",
"select * from fk_multicol_t16 order by id",
"select * from fk_multicol_t17 order by id",
"select * from fk_multicol_t19 order by id",
},
}, {
name: "Update with limit 0 success",
dataQueries: []string{
"insert into fk_multicol_t15(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t16(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t17(id, cola, colb) values (1, 7, 1)",
"insert into fk_multicol_t19(id, cola, colb) values (1, 7, 1)",
},
dmlQuery: "update fk_multicol_t15 set cola = '8' order by id limit 0",
assertionQueries: []string{
"select * from fk_multicol_t15 order by id",
"select * from fk_multicol_t16 order by id",
"select * from fk_multicol_t17 order by id",
"select * from fk_multicol_t19 order by id",
},
}, {
name: "Update with non-literal update and limit success",
dataQueries: []string{
"insert into fk_multicol_t15(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t16(id, cola, colb) values (1, 7, 1), (2, 9, 1)",
"insert into fk_multicol_t17(id, cola, colb) values (1, 7, 1)",
"insert into fk_multicol_t19(id, cola, colb) values (1, 7, 1)",
},
dmlQuery: "update fk_multicol_t15 set cola = id + 3 order by id limit 1",
assertionQueries: []string{
"select * from fk_multicol_t15 order by id",
"select * from fk_multicol_t16 order by id",
"select * from fk_multicol_t17 order by id",
"select * from fk_multicol_t19 order by id",
},
}, {
name: "Update with non-literal update order by and limit - multiple update",
dataQueries: []string{
"insert into fk_multicol_t15(id, cola, colb) values (1, 7, 1), (2, 9, 1), (3, 12, 1)",
"insert into fk_multicol_t16(id, cola, colb) values (1, 7, 1), (2, 9, 1), (3, 12, 1)",
"insert into fk_multicol_t17(id, cola, colb) values (1, 7, 1)",
"insert into fk_multicol_t19(id, cola, colb) values (1, 7, 1)",
},
dmlQuery: "update fk_multicol_t15 set cola = id + 8 order by id asc limit 2",
assertionQueries: []string{
"select * from fk_multicol_t15 order by id",
"select * from fk_multicol_t16 order by id",
"select * from fk_multicol_t17 order by id",
"select * from fk_multicol_t19 order by id",
},
}, {
name: "Update with non-literal update order by and limit - single update",
dataQueries: []string{
"insert into fk_multicol_t15(id, cola, colb) values (1, 7, 1), (2, 9, 1), (3, 12, 1)",
"insert into fk_multicol_t16(id, cola, colb) values (1, 7, 1), (2, 9, 1), (3, 12, 1)",
"insert into fk_multicol_t17(id, cola, colb) values (1, 7, 1)",
"insert into fk_multicol_t19(id, cola, colb) values (1, 7, 1)",
},
dmlQuery: "delete from fk_t15 order by id limit 0",
dmlQuery: "update fk_multicol_t15 set cola = id + 8 where id < 3 order by id desc limit 2",
assertionQueries: []string{
"select * from fk_t15 order by id",
"select * from fk_t16 order by id",
"select * from fk_t17 order by id",
"select * from fk_t19 order by id",
"select * from fk_multicol_t15 order by id",
"select * from fk_multicol_t16 order by id",
"select * from fk_multicol_t17 order by id",
"select * from fk_multicol_t19 order by id",
},
},
}
Expand All @@ -747,7 +831,12 @@ func TestFkScenarios(t *testing.T) {
}

// Run the DML query that needs to be tested and verify output with MySQL.
_, _ = mcmp.ExecAllowAndCompareError(tt.dmlQuery)
_, err := mcmp.ExecAllowAndCompareError(tt.dmlQuery)
if tt.dmlShouldErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}

// Run the assertion queries and verify we get the expected outputs.
for _, query := range tt.assertionQueries {
Expand Down
Loading
Loading