Fixed branch control issue causing a nil panic under very specific conditions

This commit is contained in:
Daylon Wilkins
2023-05-04 07:58:51 -07:00
parent 08f2ebf472
commit 40a859500f
2 changed files with 61 additions and 14 deletions

View File

@@ -226,7 +226,7 @@ ParentLoop:
copy(newSortOrders, originalSortOrders)
root.Children[newSortOrders[0]] = &MatchNode{
SortOrders: newSortOrders,
Children: nil,
Children: make(map[int32]*MatchNode),
Data: &data,
}
break
@@ -249,7 +249,7 @@ ParentLoop:
copy(newSortOrders, originalSortOrders)
newChild := &MatchNode{
SortOrders: newSortOrders,
Children: nil,
Children: make(map[int32]*MatchNode),
Data: &data,
}
root.SortOrders = root.SortOrders[:len(root.SortOrders)-len(remainingRootSortOrders)]
@@ -318,19 +318,25 @@ ParentLoop:
root.Children = nil
break
}
} else if len(root.Children) == 0 && rootParent != nil {
// With no children, we can remove this node from the parent
delete(rootParent.Children, childIndex)
// If the parent only has a single child, and it's not a destination node, we can merge that child
// with the parent
if len(rootParent.Children) == 1 && rootParent.Data == nil {
// Since there is only a single child, we merge it with this node
for _, child := range rootParent.Children {
// It was silly a few lines ago, and it's still silly here
rootParent.SortOrders = append(rootParent.SortOrders, child.SortOrders...)
rootParent.Data = child.Data
rootParent.Children = nil
} else if len(root.Children) == 0 {
if rootParent != nil {
// With no children, we can remove this node from the parent
delete(rootParent.Children, childIndex)
// If the parent only has a single child, and it's not a destination node, we can merge that child
// with the parent
if len(rootParent.Children) == 1 && rootParent.Data == nil {
// Since there is only a single child, we merge it with this node
for _, child := range rootParent.Children {
// It was silly a few lines ago, and it's still silly here
rootParent.SortOrders = append(rootParent.SortOrders, child.SortOrders...)
rootParent.Data = child.Data
rootParent.Children = child.Children
}
}
} else {
// This is the base root of the table, and it has no children (they may have been merged with
// the base root in a previous deletion), so we completely reset its sort orders to the base state
root.SortOrders = []int32{columnMarker}
}
}
// If this node has multiple children then we have nothing more to do

View File

@@ -229,3 +229,44 @@ branch', 'test', '%', 'admin')"
[ $status -ne 0 ]
[[ $output =~ "cannot create a branch" ]] || false
}
@test "branch-control: repeat deletion does not cause a nil panic" {
dolt sql <<SQL
DELETE FROM dolt_branch_control;
INSERT INTO dolt_branch_control VALUES ("dolt","s1","ab","%","admin");
INSERT INTO dolt_branch_control VALUES ("dolt","s2","ab","%","admin");
INSERT INTO dolt_branch_control VALUES ("%","%","%","%","write");
DELETE FROM dolt_branch_control;
INSERT INTO dolt_branch_control VALUES ("dolt","s1","ab","%","admin");
INSERT INTO dolt_branch_control VALUES ("dolt","s2","ab","%","admin");
INSERT INTO dolt_branch_control VALUES ("%","%","%","%","write");
DELETE FROM dolt_branch_control;
INSERT INTO dolt_branch_control VALUES ("dolt","s1","ab","%","admin");
INSERT INTO dolt_branch_control VALUES ("dolt","s2","ab","%","admin");
INSERT INTO dolt_branch_control VALUES ("%","%","%","%","write");
DELETE FROM dolt_branch_control;
INSERT INTO dolt_branch_control VALUES ("dolt","s1","ab","%","admin");
INSERT INTO dolt_branch_control VALUES ("dolt","s2","ab","%","admin");
INSERT INTO dolt_branch_control VALUES ("%","%","%","%","write");
SQL
run dolt sql -q "SELECT * FROM dolt_branch_control ORDER BY 1,2,3" -r=csv
[ $status -eq 0 ]
[ ${lines[0]} = "database,branch,user,host,permissions" ]
[ ${lines[1]} = "%,%,%,%,write" ]
[ ${lines[2]} = "dolt,s1,ab,%,admin" ]
[ ${lines[3]} = "dolt,s2,ab,%,admin" ]
# Related to the above issue, multiple deletions would report matches even when they should have all been deleted
run dolt sql -q "DELETE FROM dolt_branch_control;"
[ $status -eq 0 ]
[[ $output =~ "3 rows affected" ]] || false
run dolt sql -q "DELETE FROM dolt_branch_control;"
[ $status -eq 0 ]
[[ $output =~ "0 rows affected" ]] || false
run dolt sql -q "DELETE FROM dolt_branch_control;"
[ $status -eq 0 ]
[[ $output =~ "0 rows affected" ]] || false
run dolt sql -q "DELETE FROM dolt_branch_control;"
[ $status -eq 0 ]
[[ $output =~ "0 rows affected" ]] || false
}