/** * 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.plan.planner; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.Supplier; import org.diqube.execution.ExecutablePlanFactory; import org.diqube.execution.ExecutablePlanStep; import org.diqube.execution.consumers.ColumnDictIdConsumer; import org.diqube.execution.consumers.ColumnValueConsumer; import org.diqube.execution.consumers.RowIdConsumer; import org.diqube.executionenv.ExecutionEnvironment; /** * Resolve steps for query master. * * @author Bastian Gloeckle */ public class MasterResolveManager implements ResolveManager<ExecutablePlanStep> { private List<ExecutablePlanStep> steps = new ArrayList<ExecutablePlanStep>(); private Supplier<Integer> nextMasterIdSupplier; private ExecutionEnvironment env; private ExecutablePlanFactory executablePlanFactory; private ColumnManager<ExecutablePlanStep> columnManager; private Set<String> resolvedCols = new HashSet<>(); private MasterWireManager masterWireManager; private Set<String> requestedColNames; private ExecutablePlanStep columnValueSourceStep; public MasterResolveManager(Supplier<Integer> nextMasterIdSupplier, ExecutionEnvironment env, ExecutablePlanFactory executablePlanFactory, ColumnManager<ExecutablePlanStep> columnManager, MasterWireManager masterWireManager, Set<String> requestedColNames) { this.nextMasterIdSupplier = nextMasterIdSupplier; this.env = env; this.executablePlanFactory = executablePlanFactory; this.columnManager = columnManager; this.masterWireManager = masterWireManager; this.requestedColNames = requestedColNames; } @Override public void resolveValuesOfColumn(String colName) { if (resolvedCols.contains(colName)) return; resolvedCols.add(colName); ExecutablePlanStep resolveStep = executablePlanFactory.createResolveColumnDictIdStep(nextMasterIdSupplier.get(), env, colName); columnManager.wireOutputOfColumnIfAvailable(colName, resolveStep); steps.add(resolveStep); } /** * @param columnValueSourceStep * The {@link ExecutablePlanStep} that supports a {@link ColumnValueConsumer} output which provides all * values of all resolved columns. */ public void provideColumnValueSourceStep(ExecutablePlanStep columnValueSourceStep) { this.columnValueSourceStep = columnValueSourceStep; } /** * Call {@link #provideColumnValueSourceStep(ExecutablePlanStep)} before this! */ @Override public List<ExecutablePlanStep> build(ExecutablePlanStep rowIdSourceStep) { if (columnValueSourceStep == null) throw new IllegalStateException("No column value source specified."); // add a filter step that filters out all the columns from the result that were not requested explicitly to be // returned by the user. ExecutablePlanStep filterValuesStep = executablePlanFactory.createFilterRequestedColumnsValuesStep(nextMasterIdSupplier.get(), requestedColNames); // consume the column values from the columnValuesSourceStep masterWireManager.wire(ColumnValueConsumer.class, columnValueSourceStep, filterValuesStep); // make sure to filter all rows that are NOT provided by the rowIdSourceStep - as we might wire the ExecuteRemote // step as ColumnValue source, we need to filter out inactive rows, as these might have been merged by a // GroupIdAdjustStep. masterWireManager.wire(RowIdConsumer.class, rowIdSourceStep, filterValuesStep); if (steps.size() > 0) { // add a single resolve values step. ExecutablePlanStep resolveValueStep = executablePlanFactory.createResolveValuesStep(nextMasterIdSupplier.get()); // Just to be sure, send the results of that step to the filter step, too. masterWireManager.wire(ColumnValueConsumer.class, resolveValueStep, filterValuesStep); for (ExecutablePlanStep dictIdStep : steps) { // wire input rowID masterWireManager.wire(RowIdConsumer.class, rowIdSourceStep, dictIdStep); // wire output to resolve value step masterWireManager.wire(ColumnDictIdConsumer.class, dictIdStep, resolveValueStep); } steps.add(resolveValueStep); } steps.add(filterValuesStep); return steps; } }