package com.tesora.dve.sql.transform.strategy; /* * #%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.HashMap; import java.util.List; import java.util.Map; import com.tesora.dve.sql.node.LanguageNode; import com.tesora.dve.sql.node.Traversal; import com.tesora.dve.sql.node.expression.ExpressionNode; import com.tesora.dve.sql.node.test.EngineConstant; import com.tesora.dve.sql.util.ListSet; public class CompoundExpressionRewriter extends Traversal { protected Map<ExpressionNode, RewriterBlock> blocks; protected ExpressionNode root; public CompoundExpressionRewriter(ExpressionNode r) { super(Order.POSTORDER,ExecStyle.ONCE); blocks = new HashMap<ExpressionNode,RewriterBlock>(); root = r; traverse(r); } protected Map<ExpressionNode, RewriterBlock> getBlocks() { return blocks; } @Override public LanguageNode action(LanguageNode in) { ExpressionNode en = (ExpressionNode) in; RewriterBlock nb = new RewriterBlock(en); List<ExpressionNode> subs = en.getSubExpressions(); if (nb.isIndependent(this)) { for(ExpressionNode p : subs) blocks.remove(p); } blocks.put(en, nb); return in; } public ListSet<ExpressionNode> getFirstRewriteEntries() { RewriterBlock rb = blocks.get(root); return rb.getProjectionEntries(this); } private static class RewriterBlock { protected ExpressionNode original; protected Boolean independent = null; public RewriterBlock(ExpressionNode orig) { original = orig; } private boolean computeIndependent(CompoundExpressionRewriter cer) { if (EngineConstant.AGGFUN.has(original)) return false; List<ExpressionNode> subs = original.getSubExpressions(); for(ExpressionNode en : subs) { RewriterBlock cb = cer.getBlocks().get(en); if (cb != null && !cb.isIndependent(cer)) return false; } return true; } public boolean isIndependent(CompoundExpressionRewriter cer) { if (independent == null) independent = computeIndependent(cer); return independent.booleanValue(); } public ListSet<ExpressionNode> getProjectionEntries(CompoundExpressionRewriter cer) { ListSet<ExpressionNode> out = new ListSet<ExpressionNode>(); List<ExpressionNode> subs = original.getSubExpressions(); if (subs.isEmpty() || isIndependent(cer) || EngineConstant.AGGFUN.has(original)) { out.add(original); return out; } for(ExpressionNode en : subs) { RewriterBlock rb = cer.getBlocks().get(en); if (rb == null) continue; out.addAll(rb.getProjectionEntries(cer)); } return out; } } }