package com.tesora.dve.sql.statement.ddl; /* * #%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.ArrayList; import java.util.Collections; import java.util.List; import com.tesora.dve.exceptions.PEException; import com.tesora.dve.server.messaging.SQLCommand; import com.tesora.dve.sql.ParserException.Pass; import com.tesora.dve.sql.SchemaException; import com.tesora.dve.sql.expression.ExpressionUtils; import com.tesora.dve.sql.node.expression.ColumnInstance; import com.tesora.dve.sql.node.expression.ExpressionNode; import com.tesora.dve.sql.node.expression.FunctionCall; import com.tesora.dve.sql.node.expression.TableInstance; import com.tesora.dve.sql.node.structural.FromTableReference; import com.tesora.dve.sql.node.structural.JoinSpecification; import com.tesora.dve.sql.node.structural.JoinedTable; import com.tesora.dve.sql.node.structural.SortingSpecification; import com.tesora.dve.sql.schema.FunctionName; import com.tesora.dve.sql.schema.PEColumn; import com.tesora.dve.sql.schema.PEDatabase; import com.tesora.dve.sql.schema.PEKey; import com.tesora.dve.sql.schema.PEStorageGroup; import com.tesora.dve.sql.schema.PETable; import com.tesora.dve.sql.schema.SchemaContext; import com.tesora.dve.sql.schema.TempTable; import com.tesora.dve.sql.schema.DistributionVector.Model; import com.tesora.dve.sql.schema.modifiers.ColumnKeyModifier; import com.tesora.dve.sql.schema.modifiers.ColumnModifier; import com.tesora.dve.sql.statement.dml.AliasInformation; import com.tesora.dve.sql.statement.dml.DeleteStatement; import com.tesora.dve.sql.util.ListSet; public class AddStorageGenRangePrivateTableInfo extends AddStorageGenRangeTableInfo { private final TempTable sideTable; private final PEKey joinKey; public AddStorageGenRangePrivateTableInfo(SchemaContext sc, PETable srcTab) { super(sc, srcTab); List<PEKey> keys = srcTab.getUniqueKeys(sc); if (keys.isEmpty()) throw new SchemaException(Pass.PLANNER, "No unique key available for table " + srcTab.getName()); // we prefer primary to unique PEKey primary = null; PEKey unique = null; for(PEKey pek : keys) { if (pek.isPrimary()) primary = pek; else if (unique == null) unique = pek; else if (unique.getKeyColumns().size() > pek.getKeyColumns().size()) unique = pek; } this.joinKey = (primary != null ? primary : unique); PEDatabase pdb = srcTab.getPEDatabase(cntxt); PEStorageGroup sg = srcTab.getStorageGroup(cntxt); List<PEColumn> ttc = new ArrayList<PEColumn>(); for(PEColumn pec : joinKey.getColumns(cntxt)) { PEColumn nc = PEColumn.buildColumn(cntxt,pec.getName().getUnquotedName(), pec.getType(), Collections.<ColumnModifier> emptyList(), null, Collections.<ColumnKeyModifier> emptyList()); ttc.add(nc); } try { sideTable = TempTable.buildAdHoc(cntxt, pdb, ttc, Model.BROADCAST, Collections.<PEColumn> emptyList(), sg, true); } catch (PEException pe) { throw new SchemaException(Pass.PLANNER,"Unable to create shared side table",pe); } sideTable.addConstraint(cntxt, joinKey.getConstraint(), ttc); } @Override public boolean hasSharedTable() { return false; } @Override public TempTable getSideTable() { return sideTable; } @Override protected List<PEColumn> getFullColumns() { // we arrange for the key columns to be just after the dist key columns and before anything else ListSet<PEColumn> out = new ListSet<PEColumn>(); out.addAll(distColumns); for(PEColumn pec : joinKey.getColumns(cntxt)) out.add(pec); for(PEColumn pec : srcTab.getColumns(cntxt)) out.add(pec); return out; } // could be different public int[] getSideInsertOffsets() { List<PEColumn> fullCols = getFullColumns(); int[] out = new int[joinKey.getKeyColumns().size()]; for(int i = 0; i < joinKey.getKeyColumns().size(); i++) { out[i] = fullCols.indexOf(joinKey.getKeyColumns().get(i).getColumn()); } return out; } @Override public SQLCommand getSideDelete() { // delete a from A a inner join side s on a.uk1 = s.uk1 and a.uk2 = s.uk2 and a.uk3 = s.uk3 final TableInstance sideti = buildSideTableInstance(); final TableInstance srcti = buildSrcTableInstance(); List<ExpressionNode> equijoins = new ArrayList<ExpressionNode>(); for(int i = 0; i < joinKey.getKeyColumns().size(); i++) { equijoins.add(new FunctionCall(FunctionName.makeEquals(), new ColumnInstance(sideTable.getColumns(cntxt).get(i),sideti), new ColumnInstance(joinKey.getKeyColumns().get(i).getColumn(),srcti))); } FromTableReference ftr = new FromTableReference(srcti); JoinedTable join = new JoinedTable(sideti,ExpressionUtils.safeBuildAnd(equijoins),JoinSpecification.INNER_JOIN); ftr.addJoinedTable(join); DeleteStatement ds = new DeleteStatement(Collections.singletonList(srcti), Collections.singletonList(ftr), null, Collections.<SortingSpecification> emptyList(), null, false, new AliasInformation(), null); return getCommand(ds); } }