Skip to content

Commit

Permalink
opt: add method to add strict dependency to FuncDepSet
Browse files Browse the repository at this point in the history
This commit adds a new method, `AddStrictDependency`, to `FuncDepSet`.
This will be used in the following commit to add a dependency between
a Window operator's partition columns and its functions. Existing
methods don't work for this because the dependency is not a key.

Epic: None

Release note: None
  • Loading branch information
DrewKimball committed Dec 12, 2024
1 parent 6cb15dc commit 60c5e14
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
6 changes: 6 additions & 0 deletions pkg/sql/opt/props/func_dep.go
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,12 @@ func (f *FuncDepSet) AddEquivalency(a, b opt.ColumnID) {
f.tryToReduceKey(opt.ColSet{} /* notNullCols */)
}

// AddStrictDependency adds a new strict dependency to the set.
func (f *FuncDepSet) AddStrictDependency(from, to opt.ColSet) {
f.addDependency(from, to, true /* strict */, false /* equiv */)
f.tryToReduceKey(opt.ColSet{} /* notNullCols */)
}

// AddConstants adds a strict FD to the set that declares each given column as
// having the same constant value for all rows. If a column is nullable, then
// its value may be NULL, but then the column must be NULL for all rows. For
Expand Down
63 changes: 63 additions & 0 deletions pkg/sql/opt/props/func_dep_rand_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,67 @@ func (o *addSynthOp) ApplyToFDs(fd FuncDepSet) FuncDepSet {
return out
}

// addStrictDepOp is a test operation corresponding to AddStrictDependency.
type addStrictDepOp struct {
from, to opt.ColSet
}

func genAddStrictDep(minCols, maxCols int) testOpGenerator {
return func(tc *testConfig) testOp {
from := tc.randColSet(minCols, maxCols)
to := tc.randColSet(minCols, maxCols)
from.DifferenceWith(to)
return &addStrictDepOp{
from: from,
to: to,
}
}
}

func (o *addStrictDepOp) String() string {
return fmt.Sprintf("AddStrictDependency(%s, %s)", o.from, o.to)
}

func (o *addStrictDepOp) FilterRelation(tr testRelation) testRelation {
// Filter out rows where the from->to FD doesn't hold. The code here parallels
// that in testRelation.checkKey.
//
// We split the rows into groups (keyed on the `from` columns), picking the
// first row in each group as the "representative" of that group. All other
// rows in the group are checked against the representative row.
var out testRelation
m := make(map[rowKey]testRow)
perm := rand.Perm(len(tr))
for _, rowIdx := range perm {
r := tr[rowIdx]
k, _ := r.key(o.from)
if first, ok := m[k]; ok {
shouldFilter := false
for col, ok := o.to.Next(0); ok; col, ok = o.to.Next(col + 1) {
if first.value(col) != r.value(col) {
// Filter out row.
shouldFilter = true
break
}
}
if shouldFilter {
continue
}
} else {
m[k] = r
}
out = append(out, r)
}
return out
}

func (o *addStrictDepOp) ApplyToFDs(fd FuncDepSet) FuncDepSet {
var out FuncDepSet
out.CopyFrom(&fd)
out.AddStrictDependency(o.from, o.to)
return out
}

// testState corresponds to a chain of applied test operations. The head of a
// testStates chain has no parent and no op and just corresponds to the initial
// (empty) FDs and test relation.
Expand Down Expand Up @@ -803,6 +864,7 @@ func TestFuncDepOpsRandom(t *testing.T) {
genAddConst(1 /* minCols */, 3 /* maxCols */),
genAddEquiv(),
genAddSynth(0 /* minCols */, 3 /* maxCols */),
genAddStrictDep(0 /* minCols */, 3 /* maxCols */),
},
},

Expand All @@ -819,6 +881,7 @@ func TestFuncDepOpsRandom(t *testing.T) {
genAddConst(1 /* minCols */, 4 /* maxCols */),
genAddEquiv(),
genAddSynth(0 /* minCols */, 3 /* maxCols */),
genAddStrictDep(0 /* minCols */, 3 /* maxCols */),
},
},
}
Expand Down

0 comments on commit 60c5e14

Please sign in to comment.