Skip to content

Commit

Permalink
fix determining tables that have insert and update
Browse files Browse the repository at this point in the history
  • Loading branch information
alishakawaguchi committed Feb 6, 2025
1 parent 069cc2f commit a5d84fc
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 214 deletions.
89 changes: 5 additions & 84 deletions backend/pkg/table-dependency/circular-dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func isTableInCycles(cycles [][]string, table string) bool {
return false
}

// DetermineCycleInsertUpdateTables examines one or more cycles of tables and returns a set (as a slice)
// DetermineCycleInsertUpdateTables examines one or more cycles of tables and returns a set
// of "starting" tables. A table qualifies if it has (at least one) foreign key referencing another
// table in the cycle that is nullable. Among those qualifying tables the function “ranks” each table;
// tables that occur in more than one cycle get extra points and those with subsets get an extra bonus.
Expand Down Expand Up @@ -50,12 +50,13 @@ func DetermineCycleInsertUpdateTables(
}

// Rank each table.
// Each table gets a base rank of 1. If it appears in more than one cycle (i.e. is seen already)
// Each table gets a base rank of 1. If it appears in more than one cycle (i.e. is seen already) but not a self referencing cycle
// then add 1. If the table is in the subsets map, add 2.
for _, cycle := range possibleStarts {
for _, table := range cycle {
rank := 1
if currRank, seen := tableRankMap[table]; seen {
currRank, seen := tableRankMap[table]
if len(cycle) > 1 && seen {
rank++ // extra point for appearing in more than one cycle
tableRankMap[table] = currRank + rank
} else {
Expand Down Expand Up @@ -91,7 +92,7 @@ func DetermineCycleInsertUpdateTables(
return results, nil
}

// areAllFkColsNullable returns true if the given table has at least one foreign–key constraint
// isCycleStartEligible returns true if the given table has at least one foreign–key constraint
// (whose target table is in the given cycle) for which all columns are nullable. If there is no
// dependency in the cycle, the table qualifies (returns true).
func isCycleStartEligible(constraints []*sqlmanager_shared.ForeignConstraint, cycle []string) bool {
Expand Down Expand Up @@ -127,86 +128,6 @@ func isCycleStartEligible(constraints []*sqlmanager_shared.ForeignConstraint, cy
return !foundDependency
}

// func areAllFkColsNullable(dependencies []*sqlmanager_shared.ForeignConstraint, cycle []string) bool {
// for _, dep := range dependencies {
// if !slices.Contains(cycle, dep.ForeignKey.Table) {
// continue
// }
// for _, notNullable := range dep.NotNullable {
// if notNullable {
// return false
// }
// }
// }
// return true
// }

// func DetermineCycleStarts(
// cycles [][]string,
// subsets map[string]string,
// dependencyMap map[string][]*sqlmanager_shared.ForeignConstraint,
// ) ([]string, error) {
// tableRankMap := map[string]int{}
// possibleStarts := [][]string{}

// // FK columns must be nullable to be a starting point
// // filters out tables where foreign keys are not nullable
// for _, cycle := range cycles {
// filteredCycle := []string{}
// for _, table := range cycle {
// dependencies, ok := dependencyMap[table]
// if !ok {
// return nil, fmt.Errorf("missing dependencies for table: %s", table)
// }
// // FK columns must be nullable to be a starting point
// if areAllFkColsNullable(dependencies, cycle) {
// filteredCycle = append(filteredCycle, table)
// }
// }
// possibleStarts = append(possibleStarts, filteredCycle)
// }

// // rank each table
// for _, cycle := range possibleStarts {
// for _, table := range cycle {
// rank := 1
// currRank, seen := tableRankMap[table]
// if seen {
// // intersect table
// rank++
// }
// _, hasSubset := subsets[table]
// if hasSubset {
// rank += 2
// }
// tableRankMap[table] = rank + currRank
// }
// }

// startingTables := map[string]struct{}{}
// // for each cycle choose highest rank
// for _, cycle := range possibleStarts {
// var start *string
// rank := 0
// for _, table := range cycle {
// table := table
// tableRank := tableRankMap[table]
// if tableRank > rank {
// start = &table
// rank = tableRank
// }
// }
// if start != nil && *start != "" {
// startingTables[*start] = struct{}{}
// }
// }
// results := []string{}
// for t := range startingTables {
// results = append(results, t)
// }
// return results, nil
// }

// returns all cycles table is in
func getTableCirularDependencies(table string, circularDeps [][]string) [][]string {
cycles := [][]string{}
Expand Down
25 changes: 22 additions & 3 deletions backend/pkg/table-dependency/circular-dependencies_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func Test_uniqueCycles(t *testing.T) {
}
}

func Test_determineCycleStart(t *testing.T) {
func Test_DetermineCycleInsertUpdateTables(t *testing.T) {
tests := []struct {
name string
cycle []string
Expand Down Expand Up @@ -319,7 +319,7 @@ func Test_determineCycleStart(t *testing.T) {
}
}

func Test_determineMultiCycleStart(t *testing.T) {
func Test_DetermineCycleInsertUpdateTables_Many(t *testing.T) {
tests := []struct {
name string
cycles [][]string
Expand Down Expand Up @@ -430,6 +430,25 @@ func Test_determineMultiCycleStart(t *testing.T) {
expected: []string{"a", "b"},
expectError: false,
},
{
name: "multi cycle with self reference",
cycles: [][]string{{"public.a", "public.b", "public.c"}, {"public.b"}},
subsets: map[string]string{},
dependencyMap: map[string][]*sqlmanager_shared.ForeignConstraint{
"public.a": {
{Columns: []string{"b_id"}, NotNullable: []bool{false}, ForeignKey: &sqlmanager_shared.ForeignKey{Table: "public.b", Columns: []string{"id"}}},
},
"public.b": {
{Columns: []string{"c_id"}, NotNullable: []bool{true}, ForeignKey: &sqlmanager_shared.ForeignKey{Table: "public.c", Columns: []string{"id"}}},
{Columns: []string{"bb_id"}, NotNullable: []bool{false}, ForeignKey: &sqlmanager_shared.ForeignKey{Table: "public.b", Columns: []string{"id"}}},
},
"public.c": {
{Columns: []string{"a_id"}, NotNullable: []bool{true}, ForeignKey: &sqlmanager_shared.ForeignKey{Table: "public.a", Columns: []string{"id"}}},
},
},
expected: []string{"public.a", "public.b"},
expectError: false,
},
}

for _, tt := range tests {
Expand All @@ -445,7 +464,7 @@ func Test_determineMultiCycleStart(t *testing.T) {
}
}

func Test_determineSingleCycleMultipleStarts_SplitNullable(t *testing.T) {
func Test_DetermineCycleInsertUpdateTables_SplitNullable(t *testing.T) {
cycles := [][]string{{"public.a", "public.b", "public.c"}}
subsets := map[string]string{}
dependencyMap := map[string][]*sqlmanager_shared.ForeignConstraint{
Expand Down
Loading

0 comments on commit a5d84fc

Please sign in to comment.