Skip to content

Commit

Permalink
add dag for func deps
Browse files Browse the repository at this point in the history
  • Loading branch information
keanji-x committed Apr 19, 2024
1 parent debb83f commit b1b8373
Show file tree
Hide file tree
Showing 3 changed files with 237 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package org.apache.doris.nereids.properties;

import org.apache.doris.nereids.trees.expressions.Slot;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
* Function dependence items.
*/
public class FuncDeps {
class FuncDepsItem {
final Set<Slot> determinants;
final Set<Slot> dependencies;

public FuncDepsItem(Set<Slot> determinants, Set<Slot> dependencies) {
this.determinants = determinants;
this.dependencies = dependencies;
}

@Override
public String toString() {
return String.format("%s -> %s", determinants, dependencies);
}
}

private final List<FuncDepsItem> items;

FuncDeps() {
items = new ArrayList<>();
}

public void addFuncItems(Set<Slot> determinants, Set<Slot> dependencies) {
items.add(new FuncDepsItem(determinants, dependencies));
}

public int size() {
return items.size();
}

@Override
public String toString() {
return items.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package org.apache.doris.nereids.properties;

import org.apache.doris.nereids.trees.expressions.Slot;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
* Function dependence items.
*/
public class FuncDepsDAG {
class DAGItem {
Set<Slot> slots;
Set<DAGItem> parents;
Set<DAGItem> children;

public DAGItem(Set<Slot> slots) {
this.slots = slots;
this.parents = new HashSet<>();
this.children = new HashSet<>();
}
}

private Map<Set<Slot>, DAGItem> itemMap;

public FuncDepsDAG() {
itemMap = new HashMap<>();
}

public void addDeps(Set<Slot> l, Set<Slot> r) {
DAGItem lNode = getOrCreateNode(l);
DAGItem rNode = getOrCreateNode(r);
addEdge(lNode, rNode);
}

private DAGItem getOrCreateNode(Set<Slot> slots) {
return itemMap.computeIfAbsent(slots, DAGItem::new);
}

private void addEdge(DAGItem from, DAGItem to) {
if (!from.children.contains(to)) {
from.children.add(to);
to.parents.add(from);
}
}

/**
* find all func deps
*/
public FuncDeps findValidFuncDeps(Set<Slot> validSlot) {
FuncDeps res = new FuncDeps();
for (Entry<Set<Slot>, DAGItem> entry : itemMap.entrySet()) {
if (validSlot.containsAll(entry.getKey())) {
Set<DAGItem> visited = new HashSet<>();
Set<DAGItem> children = new HashSet<>();
visited.add(entry.getValue());
collectAllChildren(validSlot, entry.getValue(), visited, children);
for (DAGItem child : children) {
res.addFuncItems(entry.getValue().slots, child.slots);
}
}
}
return res;
}

private void collectAllChildren(Set<Slot> validSlot, DAGItem root,
Set<DAGItem> visited, Set<DAGItem> children) {
for (DAGItem child : root.children) {
if (visited.contains(child)) {
continue;
}
if (validSlot.containsAll(child.slots)) {
children.add(child);
}
visited.add(child);
collectAllChildren(validSlot, child, visited, children);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package org.apache.doris.nereids.properties;

import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.expressions.SlotReference;
import org.apache.doris.nereids.types.IntegerType;

import com.google.common.collect.Sets;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

class FuncDepsDAGTest {
@Test
void testBasic() {
FuncDepsDAG dag = new FuncDepsDAG();
Slot s1 = new SlotReference("s1", IntegerType.INSTANCE);
Slot s2 = new SlotReference("s2", IntegerType.INSTANCE);
dag.addDeps(Sets.newHashSet(s1), Sets.newHashSet(s2));
FuncDeps res = dag.findValidFuncDeps(Sets.newHashSet(s1, s2));
Assertions.assertEquals(1, res.size());
}

@Test
void testTrans() {
FuncDepsDAG dag = new FuncDepsDAG();
Slot s1 = new SlotReference("s1", IntegerType.INSTANCE);
Slot s2 = new SlotReference("s2", IntegerType.INSTANCE);
Slot s3 = new SlotReference("s3", IntegerType.INSTANCE);
dag.addDeps(Sets.newHashSet(s1), Sets.newHashSet(s2));
dag.addDeps(Sets.newHashSet(s2), Sets.newHashSet(s3));
FuncDeps res = dag.findValidFuncDeps(Sets.newHashSet(s1, s3));
Assertions.assertEquals(1, res.size());
}

@Test
void testCircle() {
FuncDepsDAG dag = new FuncDepsDAG();
Slot s1 = new SlotReference("s1", IntegerType.INSTANCE);
Slot s2 = new SlotReference("s2", IntegerType.INSTANCE);
dag.addDeps(Sets.newHashSet(s1), Sets.newHashSet(s2));
dag.addDeps(Sets.newHashSet(s2), Sets.newHashSet(s1));
FuncDeps res = dag.findValidFuncDeps(Sets.newHashSet(s1, s2));
Assertions.assertEquals(2, res.size());
}

@Test
void testTree() {
FuncDepsDAG dag = new FuncDepsDAG();
Slot s1 = new SlotReference("s1", IntegerType.INSTANCE);
Slot s2 = new SlotReference("s2", IntegerType.INSTANCE);
Slot s3 = new SlotReference("s3", IntegerType.INSTANCE);
Slot s4 = new SlotReference("s4", IntegerType.INSTANCE);
dag.addDeps(Sets.newHashSet(s1), Sets.newHashSet(s2));
dag.addDeps(Sets.newHashSet(s2), Sets.newHashSet(s3));
dag.addDeps(Sets.newHashSet(s2), Sets.newHashSet(s4));
FuncDeps res = dag.findValidFuncDeps(Sets.newHashSet(s1, s4, s3));
Assertions.assertEquals(2, res.size());
}
}

0 comments on commit b1b8373

Please sign in to comment.