/** * diqube: Distributed Query Base. * * Copyright (C) 2015 Bastian Gloeckle * * This file is part of diqube. * * diqube is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.diqube.optimize; import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import org.diqube.diql.request.ComparisonRequest; import org.diqube.diql.request.ComparisonRequest.DelegateComparisonRequest; import org.diqube.diql.request.ComparisonRequest.Leaf; import org.diqube.diql.request.ComparisonRequest.Not; import org.diqube.diql.request.ComparisonRequest.Operator; import org.diqube.util.Pair; /** * Builds all {@link OptimizerComparisonInfo} on {@link ComparisonRequest}s. * * @author Bastian Gloeckle */ public class OptimizerComparisonInfoBuilder { private ComparisonRequest request; public OptimizerComparisonInfoBuilder() { } public OptimizerComparisonInfoBuilder withComparisonRequest(ComparisonRequest request) { this.request = request; return this; } /** * @return map from {@link ComparisonRequest#getVirtualId()} to {@link OptimizerComparisonInfo} belonging to it. */ public Map<UUID, OptimizerComparisonInfo> build() { Pair<Map<UUID, ComparisonRequest>, Map<UUID, OptimizerComparisonInfo>> p = initialize(); updateTransitivelyContainsOnlyEquals(p.getLeft(), p.getRight()); return p.getRight(); } private void updateTransitivelyContainsOnlyEquals(Map<UUID, ComparisonRequest> idToRequest, Map<UUID, OptimizerComparisonInfo> idToOptimizerInfo) { Set<UUID> idsAllChildrenEquals = new HashSet<>(idToRequest.keySet()); // Pair: VirtualId of request to "all children are equals". Deque<Pair<UUID, Boolean>> allRequests = new LinkedList<>(); idToRequest.entrySet().stream().filter(e -> e.getValue() instanceof Leaf) .forEach(e -> allRequests.add(new Pair<>(e.getKey(), true))); while (!allRequests.isEmpty()) { Pair<UUID, Boolean> p = allRequests.poll(); UUID reqId = p.getLeft(); Boolean allChildrenAreEquals = p.getRight(); ComparisonRequest req = idToRequest.get(reqId); if (req instanceof Leaf) allChildrenAreEquals &= ((Leaf) req).getOp().equals(Operator.EQ); if (!allChildrenAreEquals) idsAllChildrenEquals.remove(reqId); OptimizerComparisonInfo info = idToOptimizerInfo.get(req.getVirtualId()); if (info.getParent() != null) allRequests.add(new Pair<>(info.getParent().getVirtualId(), allChildrenAreEquals)); } for (Entry<UUID, ComparisonRequest> e : idToRequest.entrySet()) idToOptimizerInfo.get(e.getKey()).setTransitivelyContainsOnlyEquals(idsAllChildrenEquals.contains(e.getKey())); } private Pair<Map<UUID, ComparisonRequest>, Map<UUID, OptimizerComparisonInfo>> initialize() { Map<UUID, ComparisonRequest> idToRequest = new HashMap<>(); Map<UUID, OptimizerComparisonInfo> idToOptimizerInfo = new HashMap<>(); // request/parent pairs Deque<Pair<ComparisonRequest, ComparisonRequest>> allRequests = new LinkedList<>(); allRequests.add(new Pair<>(request, null)); while (!allRequests.isEmpty()) { Pair<ComparisonRequest, ComparisonRequest> p = allRequests.poll(); ComparisonRequest curReq = p.getLeft(); ComparisonRequest parent = p.getRight(); idToRequest.put(curReq.getVirtualId(), curReq); OptimizerComparisonInfo newInfo = new OptimizerComparisonInfo(curReq.getVirtualId()); newInfo.setParent(parent); idToOptimizerInfo.put(curReq.getVirtualId(), newInfo); if (curReq instanceof DelegateComparisonRequest) { allRequests.add(new Pair<>(((DelegateComparisonRequest) curReq).getLeft(), curReq)); allRequests.add(new Pair<>(((DelegateComparisonRequest) curReq).getRight(), curReq)); } else if (curReq instanceof Not) { allRequests.add(new Pair<>(((Not) curReq).getChild(), curReq)); } } return new Pair<>(idToRequest, idToOptimizerInfo); } }