/* This file is part of VoltDB.
* Copyright (C) 2008-2017 VoltDB Inc.
*
* This program 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 VoltDB. If not, see <http://www.gnu.org/licenses/>.
*/
package org.voltdb.planner.parseinfo;
import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.voltdb.expressions.AbstractExpression;
import org.voltdb.expressions.ExpressionUtil;
/**
* An object of class SubqueryLeafNode is a leaf in a join expression tree
* which corresponds to a subquery.
*/
public class SubqueryLeafNode extends JoinNode{
private final StmtSubqueryScan m_subqueryScan;
/**
* Construct a subquery node
* @param id - node unique id
* @param table - join table index
* @param joinExpr - join expression
* @param whereExpr - filter expression
* @param id - node id
*/
public SubqueryLeafNode(int id,
AbstractExpression joinExpr, AbstractExpression whereExpr, StmtSubqueryScan scan) {
super(id);
m_joinExpr = joinExpr;
m_whereExpr = whereExpr;
m_subqueryScan = scan;
}
/**
* Deep clone
*/
@Override
public Object clone() {
AbstractExpression joinExpr = (m_joinExpr != null) ?
(AbstractExpression) m_joinExpr.clone() : null;
AbstractExpression whereExpr = (m_whereExpr != null) ?
(AbstractExpression) m_whereExpr.clone() : null;
JoinNode newNode = new SubqueryLeafNode(m_id, joinExpr, whereExpr, m_subqueryScan);
return newNode;
}
@Override
public JoinNode cloneWithoutFilters() {
JoinNode newNode = new SubqueryLeafNode(m_id, null, null, m_subqueryScan);
return newNode;
}
@Override
public void extractSubQueries(List<StmtSubqueryScan> subQueries) {
subQueries.add(m_subqueryScan);
}
public StmtSubqueryScan getSubqueryScan() { return m_subqueryScan; }
@Override
public StmtTableScan getTableScan() { return m_subqueryScan; }
@Override
public String getTableAlias() { return m_subqueryScan.getTableAlias(); }
@Override
public void analyzeJoinExpressions(List<AbstractExpression> noneList) {
m_joinInnerList.addAll(ExpressionUtil.uncombineAny(getJoinExpression()));
m_whereInnerList.addAll(ExpressionUtil.uncombineAny(getWhereExpression()));
}
@Override
protected void collectEquivalenceFilters(HashMap<AbstractExpression,
Set<AbstractExpression>> equivalenceSet,
ArrayDeque<JoinNode> joinNodes) {
if ( ! m_whereInnerList.isEmpty()) {
ExpressionUtil.collectPartitioningFilters(m_whereInnerList,
equivalenceSet);
}
// HSQL sometimes tags single-table filters in inner joins as join clauses
// rather than where clauses? OR does analyzeJoinExpressions correct for this?
// If so, these CAN contain constant equivalences that get used as the basis for equivalence
// conditions that determine partitioning, so process them as where clauses.
if ( ! m_joinInnerList.isEmpty()) {
ExpressionUtil.collectPartitioningFilters(m_joinInnerList,
equivalenceSet);
}
}
}