package com.tesora.dve.sql.transform; /* * #%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.sql.expression.Visitor; import com.tesora.dve.sql.expression.VisitorContext; import com.tesora.dve.sql.node.LanguageNode; import com.tesora.dve.sql.node.expression.ExpressionNode; import com.tesora.dve.sql.node.expression.TableJoin; import com.tesora.dve.sql.node.structural.FromTableReference; import com.tesora.dve.sql.node.structural.JoinedTable; import com.tesora.dve.sql.node.structural.LimitSpecification; import com.tesora.dve.sql.node.structural.SortingSpecification; import com.tesora.dve.sql.statement.dml.AliasInformation; import com.tesora.dve.sql.statement.dml.DMLStatement; import com.tesora.dve.sql.statement.dml.DeleteStatement; import com.tesora.dve.sql.statement.dml.InsertIntoSelectStatement; import com.tesora.dve.sql.statement.dml.InsertIntoValuesStatement; import com.tesora.dve.sql.statement.dml.ProjectingStatement; import com.tesora.dve.sql.statement.dml.ReplaceIntoSelectStatement; import com.tesora.dve.sql.statement.dml.ReplaceIntoValuesStatement; import com.tesora.dve.sql.statement.dml.SelectStatement; import com.tesora.dve.sql.statement.dml.TruncateStatement; import com.tesora.dve.sql.statement.dml.UnionStatement; import com.tesora.dve.sql.statement.dml.UpdateStatement; public final class CopyVisitor extends Visitor { private final CopyContext forwarding; private CopyVisitor(CopyContext cc) { forwarding = cc; } @Override public VisitorContext newContext() { return forwarding; } @SuppressWarnings("unchecked") public static <S extends DMLStatement> S copy(S in) { CopyContext cc = new CopyContext("CopyVisitor.copy(DMLStatement)"); CopyVisitor cv = new CopyVisitor(cc); S out = (S) cv.visit(in); SchemaMapper sm = new SchemaMapper(Collections.singleton((DMLStatement)in), out, cc); out.setMapper(sm); return out; } @SuppressWarnings("unchecked") public static <T extends LanguageNode> T copy(T in, CopyContext cc) { CopyVisitor cv = new CopyVisitor(cc); return (T) cv.visit(in); } @SuppressWarnings("unchecked") public static <T extends ProjectingStatement> T copy(T in, CopyContext cc) { CopyVisitor cv = new CopyVisitor(cc); T out = (T) cv.visit(in); boolean was = cc.isFixed(); SchemaMapper sm = new SchemaMapper(Collections.singleton((DMLStatement)in), out, cc); cc.setFixed(was); out.setMapper(sm); return out; } @Override public <I extends LanguageNode> List<I> visit(List<I> l, VisitorContext vc) { if (l == null) return l; ArrayList<I> out = new ArrayList<I>(); for(I t : l) out.add(visit(t, vc)); return out; } @Override public ExpressionNode visitExpression(ExpressionNode in, VisitorContext vc) { CopyContext cvc = (CopyContext) vc; return (ExpressionNode)in.copy(cvc); } @Override public SelectStatement visitSelectStatement(SelectStatement ss, VisitorContext vc) { CopyContext cc = (CopyContext) vc; cc.pushScope(); SelectStatement nss = new SelectStatement( visit(ss.getTables(),vc), visit(ss.getProjection(),vc), visit(ss.getWhereClause(),vc), visit(ss.getOrderBys(),vc), visit(ss.getLimit(),vc), ss.getSetQuantifier(), ss.getSelectOptions(), visit(ss.getGroupBys(),vc), visit(ss.getHavingExpression(),vc), ss.isLocking(), new AliasInformation(ss.getAliases()), ss.getSourceLocation()); nss.setGrouped(ss.isGrouped()); nss.getDerivedInfo().copyTake(ss.getDerivedInfo()); nss.getDerivedInfo().takeCopy(cc); cc.popScope(); cc.registerProjectingStatement(nss); return nss; } @Override public UpdateStatement visitUpdateStatement(UpdateStatement in, VisitorContext vc) { CopyContext cc = (CopyContext) vc; cc.pushScope(); UpdateStatement us = new UpdateStatement(visit(in.getTables(),vc), visit(in.getUpdateExpressions(),vc), visit(in.getWhereClause(),vc), visit(in.getOrderBys(),vc), visit(in.getLimit(),vc), new AliasInformation(in.getAliases()), in.getSourceLocation()); us.getDerivedInfo().copyTake(in.getDerivedInfo()); us.getDerivedInfo().takeCopy(cc); cc.popScope(); return us; } @Override public DeleteStatement visitDeleteStatement(DeleteStatement in, VisitorContext vc) { CopyContext cc = (CopyContext) vc; cc.pushScope(); DeleteStatement ds = new DeleteStatement(visit(in.getTargetDeletes(),vc), visit(in.getTables(),vc), visit(in.getWhereClause(),vc), visit(in.getOrderBys(),vc), visit(in.getLimit(),vc), in.isTruncate(), new AliasInformation(), in.getSourceLocation()); ds.getDerivedInfo().copyTake(in.getDerivedInfo()); ds.getDerivedInfo().takeCopy(cc); cc.popScope(); return ds; } @Override public InsertIntoValuesStatement visitInsertIntoValuesStatement(InsertIntoValuesStatement is, VisitorContext vc) { List<List<ExpressionNode>> values = new ArrayList<List<ExpressionNode>>(); for(List<ExpressionNode> row : is.getValues()) { List<ExpressionNode> rowCopy = visit(row, vc); values.add(rowCopy); } InsertIntoValuesStatement nis = new InsertIntoValuesStatement(visit(is.getTableInstance(),vc), visit(is.getColumnSpecification(),vc), values, visit(is.getOnDuplicateKey(),vc), new AliasInformation(), is.getSourceLocation()); nis.getDerivedInfo().copyTake(is.getDerivedInfo()); return nis; } @Override public ReplaceIntoValuesStatement visitReplaceIntoValuesStatement(ReplaceIntoValuesStatement is, VisitorContext vc) { List<List<ExpressionNode>> values = new ArrayList<List<ExpressionNode>>(); for(List<ExpressionNode> row : is.getValues()) { List<ExpressionNode> rowCopy = visit(row, vc); values.add(rowCopy); } ReplaceIntoValuesStatement nis = new ReplaceIntoValuesStatement(visit(is.getTableInstance(),vc), visit(is.getColumnSpecification(),vc), values, new AliasInformation(), is.getSourceLocation()); nis.getDerivedInfo().copyTake(is.getDerivedInfo()); return nis; } @Override public InsertIntoSelectStatement visitInsertIntoSelectStatement(InsertIntoSelectStatement iiss, VisitorContext vc) { CopyContext cc = (CopyContext) vc; cc.pushScope(); InsertIntoSelectStatement ns = new InsertIntoSelectStatement(visit(iiss.getTableInstance(),vc), visit(iiss.getColumnSpecification(),vc), visit(iiss.getSource(),vc), iiss.isNestedGrouped(), visit(iiss.getOnDuplicateKey(),vc), new AliasInformation(), iiss.getSourceLocation()); ns.getDerivedInfo().copyTake(iiss.getDerivedInfo()); ns.getDerivedInfo().takeCopy(cc); cc.popScope(); return ns; } @Override public ReplaceIntoSelectStatement visitReplaceIntoSelectStatement(ReplaceIntoSelectStatement iiss, VisitorContext vc) { CopyContext cc = (CopyContext) vc; cc.pushScope(); ReplaceIntoSelectStatement ns = new ReplaceIntoSelectStatement(visit(iiss.getTableInstance(),vc), visit(iiss.getColumnSpecification(),vc), visit(iiss.getSource(),vc), iiss.isNestedGrouped(), new AliasInformation(), iiss.getSourceLocation()); ns.getDerivedInfo().copyTake(iiss.getDerivedInfo()); ns.getDerivedInfo().takeCopy(cc); cc.popScope(); return ns; } public TruncateStatement visitTruncateStatement(TruncateStatement ts, VisitorContext vc) { return new TruncateStatement(visit(ts.getTruncatedTable(), vc), ts.getSourceLocation()); } @Override public UnionStatement visitUnionStatement(UnionStatement us, VisitorContext vc) { CopyContext cc = (CopyContext) vc; cc.pushScope(); UnionStatement nus = new UnionStatement(visit(us.getFromEdge().get(), vc), visit(us.getToEdge().get(), vc), us.isUnionAll(),us.getSourceLocation()); nus.setOrderBy(visit(us.getOrderBys(), vc)); nus.setLimit(visit(us.getLimit(),vc)); nus.setGrouped(us.isGrouped()); nus.getDerivedInfo().copyTake(us.getDerivedInfo()); nus.getDerivedInfo().takeCopy(cc); cc.popScope(); cc.registerProjectingStatement(nus); return nus; } @Override public FromTableReference visitFromTableReference(FromTableReference in, VisitorContext vc) { return new FromTableReference(visit(in.getTarget(),vc)); } @Override public TableJoin visitTableJoin(TableJoin tj, VisitorContext vc) { return new TableJoin(visit(tj.getFactor(),vc), visit(tj.getJoins(),vc)); } @Override public JoinedTable visitJoinedTable(JoinedTable in, VisitorContext vc) { return new JoinedTable(visit(in.getJoinedTo(),vc), visit(in.getJoinOn(),vc), in.getJoinType()); } @Override public LimitSpecification visitLimitSpecification(LimitSpecification in, VisitorContext vc) { return new LimitSpecification(visit(in.getRowcount(),vc),visit(in.getOffset(),vc)); } @Override public SortingSpecification visitSortingSpecification(SortingSpecification in, VisitorContext vc) { return new SortingSpecification(visit(in.getTarget(),vc),in.isAscending()); } }