package com.tesora.dve.sql.transform.strategy.featureplan; /* * #%L * Tesora Inc. * Database Virtualization Engine * %% * Copyright (C) 2011 - 2014 Tesora Inc. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * 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/>. * #L% */ import java.util.List; import com.tesora.dve.exceptions.PEException; import com.tesora.dve.sql.expression.MTTableKey; import com.tesora.dve.sql.expression.TableKey; import com.tesora.dve.sql.node.expression.ExpressionNode; import com.tesora.dve.sql.schema.Database; import com.tesora.dve.sql.schema.DistributionKeyTemplate; import com.tesora.dve.sql.schema.PEStorageGroup; import com.tesora.dve.sql.schema.TempTable; import com.tesora.dve.sql.statement.dml.DMLStatement; import com.tesora.dve.sql.statement.dml.ProjectingStatement; import com.tesora.dve.sql.statement.dml.SelectStatement; import com.tesora.dve.sql.transform.behaviors.defaults.DefaultFeatureStepBuilder; import com.tesora.dve.sql.transform.execution.DMLExplainRecord; import com.tesora.dve.sql.transform.execution.ExecutionSequence; import com.tesora.dve.sql.transform.execution.RedistributionExecutionStep; import com.tesora.dve.sql.transform.strategy.ExecutionCost; import com.tesora.dve.sql.transform.strategy.PlannerContext; public class RedistFeatureStep extends FeatureStep { private final ProjectingFeatureStep source; private final PEStorageGroup targetGroup; private final TableKey targetTable; private final List<Integer> keyOffsets; private final RedistributionFlags flags; public RedistFeatureStep(FeaturePlanner planner, ProjectingFeatureStep src,TableKey targetTable, PEStorageGroup targetGroup, List<Integer> distOnOffsets, RedistributionFlags flags) { super(planner, src.getSourceGroup(), src.getDistributionKey()); this.source = src; this.targetTable = targetTable; this.targetGroup = targetGroup; this.keyOffsets = distOnOffsets; this.flags = flags; // we assume our src's children getSelfChildren().addAll(src.getAllChildren()); } public ProjectingFeatureStep getSourceStep() { return source; } private static final RedistributionFlags missingFlags = new RedistributionFlags(); @Override public void scheduleSelf(PlannerContext pc, ExecutionSequence es) throws PEException { DistributionKeyTemplate dkt = new DistributionKeyTemplate(targetTable.getAbstractTable()); int counter = 1; List<ExpressionNode> projection = ((ProjectingStatement)source.getPlannedStatement()).getProjections().get(0); for(Integer i : keyOffsets) { dkt.addColumn(projection.get(i.intValue()), counter++); } RedistributionFlags rf = (flags == null ? missingFlags : flags); es.append(RedistributionExecutionStep.build(pc.getContext(), source.getDatabase(pc), source.getSourceGroup(), source.getDistributionVector(), (ProjectingStatement)source.getPlannedStatement(), targetGroup, targetTable.getAbstractTable().asTable(), (targetTable instanceof MTTableKey ? ((MTTableKey)targetTable).getScope() : null), dkt, rf.getMissingAutoIncrement(), rf.getOffsetOfExistingAutoInc(), rf.getOnDuplicateKey(), rf.getUseRowCount(), source.getDistributionKey(), rf.isMustEnforceScalarValue(), rf.isInsertIgnore(), rf.getGenerator(), getExplainRecord())); } @Override public DMLStatement getPlannedStatement() { return source.getPlannedStatement(); } @Override public Database<?> getDatabase(PlannerContext pc) { return source.getDatabase(pc); } public TableKey getTargetTable() { return targetTable; } public ProjectingFeatureStep buildNewProjectingStep(PlannerContext pc, FeaturePlanner planner, ExecutionCost newCost, DMLExplainRecord splain) throws PEException { TempTable tt = getTargetTempTable(); if (tt == null) return null; SelectStatement intent = tt.buildSelect(pc.getContext()); ProjectingFeatureStep out = DefaultFeatureStepBuilder.INSTANCE.buildProjectingStep(pc, planner, intent, (newCost != null ? newCost : source.getCost()), targetGroup, getPlannedStatement().getDatabase(pc.getContext()), tt.getDistributionVector(pc.getContext()), null, splain); out.addChild(this); return out; } public ProjectingFeatureStep buildTriggerRowsStep(PlannerContext pc, FeaturePlanner planner) throws PEException { TempTable tt = getTargetTempTable(); if (tt == null) return null; SelectStatement intent = tt.buildSelect(pc.getContext()); ProjectingFeatureStep out = DefaultFeatureStepBuilder.INSTANCE.buildProjectingStep(pc, planner, intent, source.getCost(), targetGroup, getPlannedStatement().getDatabase(pc.getContext()), tt.getDistributionVector(pc.getContext()), null, null); // don't thread self in - the step is executed outside of the normal flow return out; } public SelectStatement buildNewSelect(PlannerContext pc) throws PEException { TempTable tt = getTargetTempTable(); if (tt == null) return null; SelectStatement intent = tt.buildSelect(pc.getContext()); return intent; } public TempTable getTargetTempTable() { if (targetTable.getAbstractTable().isTempTable()) { return (TempTable) targetTable.getAbstractTable(); } return null; } }