package com.taobao.tddl.optimizer.core.plan.bean;
import static com.taobao.tddl.optimizer.utils.OptimizerToString.appendField;
import static com.taobao.tddl.optimizer.utils.OptimizerToString.appendln;
import static com.taobao.tddl.optimizer.utils.OptimizerToString.printFilterString;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.taobao.tddl.common.jdbc.ParameterContext;
import com.taobao.tddl.optimizer.core.ASTNodeFactory;
import com.taobao.tddl.optimizer.core.PlanVisitor;
import com.taobao.tddl.optimizer.core.expression.IFilter;
import com.taobao.tddl.optimizer.core.expression.ISelectable;
import com.taobao.tddl.optimizer.core.plan.IQueryTree;
import com.taobao.tddl.optimizer.core.plan.query.IJoin;
import com.taobao.tddl.optimizer.utils.OptimizerToString;
public class Join extends QueryTree implements IJoin {
/**
* 左面join 子树 所有join都以key-value对的形式存在
*/
protected IQueryTree left;
/**
* 右面join 子树 所有join的子节点都以key-value对的形式存在
*/
protected IQueryTree right;
/**
* 左面join的列
*/
protected List<ISelectable> leftColumns = new LinkedList<ISelectable>();
/**
* 右面join的对应列
*/
protected List<ISelectable> rightColumns = new LinkedList<ISelectable>(); ;
/**
* 非column=column的join列
*/
protected IFilter otherJoinOnFilter;
/**
* join的策略 ,具体请看对应解说
*/
protected JoinStrategy joinStrategy;
/**
* 左outer join,即使右表没有匹配的对应行,也输出左行 默认是false,也就是内联join
*/
protected Boolean leftOuter;
/**
* 右outer join 即使左表没有匹配的对应行,也输出右行 默认是false,也就是内联join
*/
protected Boolean rightOuter;
protected IFilter whereFilter;
public IJoin copy() {
IJoin join = ASTNodeFactory.getInstance().createJoin();
copySelfTo((QueryTree) join);
join.setJoinNodes(this.getLeftNode(), this.getRightNode());
join.setJoinOnColumns(this.getLeftJoinOnColumns(), this.getRightJoinOnColumns());
join.setJoinStrategy(this.getJoinStrategy());
join.setLeftOuter(this.getLeftOuter());
join.setRightOuter(this.getRightOuter());
join.setOtherJoinOnFilter((IFilter) (otherJoinOnFilter == null ? null : otherJoinOnFilter.copy()));
join.setWhereFilter(this.getWhereFilter());
return join;
}
public Join assignment(Map<Integer, ParameterContext> parameterSettings) {
super.assignment(parameterSettings);
IQueryTree left = getLeftNode();
if (left != null) {
left.assignment(parameterSettings);
}
IQueryTree right = getRightNode();
if (right != null) {
right.assignment(parameterSettings);
}
if (this.otherJoinOnFilter != null) {
otherJoinOnFilter = (IFilter) otherJoinOnFilter.assignment(parameterSettings);
}
return this;
}
public void accept(PlanVisitor visitor) {
visitor.visit(this);
}
public IJoin setJoinNodes(IQueryTree left, IQueryTree right) {
this.left = left;
this.right = right;
return this;
}
public IJoin setLeftNode(IQueryTree left) {
this.left = left;
return this;
}
public IQueryTree getLeftNode() {
return left;
}
public IJoin setRightNode(IQueryTree right) {
this.right = right;
return this;
}
public IQueryTree getRightNode() {
return right;
}
public IJoin setJoinOnColumns(List<ISelectable> leftColumns, List<ISelectable> rightColumns) {
this.leftColumns = leftColumns;
this.rightColumns = rightColumns;
return this;
}
public IJoin addLeftJoinOnColumn(ISelectable left) {
this.leftColumns.add(left);
return this;
}
public List<ISelectable> getLeftJoinOnColumns() {
return leftColumns;
}
public IJoin addRightJoinOnColumn(ISelectable right) {
rightColumns.add(right);
return this;
}
public List<ISelectable> getRightJoinOnColumns() {
return rightColumns;
}
public IJoin setJoinStrategy(JoinStrategy joinStrategy) {
this.joinStrategy = joinStrategy;
return this;
}
public JoinStrategy getJoinStrategy() {
return joinStrategy;
}
public Boolean getLeftOuter() {
return leftOuter;
}
public Boolean getRightOuter() {
return rightOuter;
}
public IJoin setLeftOuter(boolean on_off) {
this.leftOuter = on_off;
return this;
}
public IJoin setRightOuter(boolean on_off) {
this.rightOuter = on_off;
return this;
}
public IFilter getOtherJoinOnFilter() {
return otherJoinOnFilter;
}
public IJoin setOtherJoinOnFilter(IFilter otherJoinOnFilter) {
this.otherJoinOnFilter = otherJoinOnFilter;
return this;
}
public IFilter getWhereFilter() {
return whereFilter;
}
public IJoin setWhereFilter(IFilter whereFilter) {
this.whereFilter = whereFilter;
return this;
}
public String toStringWithInden(int inden) {
String tabTittle = OptimizerToString.getTab(inden);
String tabContent = OptimizerToString.getTab(inden + 1);
StringBuilder sb = new StringBuilder();
if (this.getAlias() != null) {
appendln(sb, tabTittle + "Join" + " as " + this.getAlias());
} else {
appendln(sb, tabTittle + "Join");
}
appendField(sb, "leftColumns", this.getLeftJoinOnColumns(), tabContent);
appendField(sb, "rightColumns", this.getRightJoinOnColumns(), tabContent);
if (this.leftOuter && this.rightOuter) {
appendField(sb, "type", "outter join", tabContent);
}
if (!this.leftOuter && this.rightOuter) {
appendField(sb, "type", "right outter join", tabContent);
}
if (this.leftOuter && !this.rightOuter) {
appendField(sb, "type", "left outter join", tabContent);
}
if (!this.leftOuter && !this.rightOuter) {
appendField(sb, "type", "inner join", tabContent);
}
appendField(sb, "valueFilter", printFilterString(this.getValueFilter()), tabContent);
appendField(sb, "otherJoinOnFilter", printFilterString(this.getOtherJoinOnFilter()), tabContent);
appendField(sb, "having", printFilterString(this.getHavingFilter()), tabContent);
if (!(this.getLimitFrom() != null && this.getLimitFrom().equals(-1L) && this.getLimitTo() != null && this.getLimitTo()
.equals(-1L))) {
appendField(sb, "limitFrom", this.getLimitFrom(), tabContent);
appendField(sb, "limitTo", this.getLimitTo(), tabContent);
}
if (this.isSubQuery() != null && this.isSubQuery()) {
appendField(sb, "isSubQuery", this.isSubQuery(), tabContent);
}
appendField(sb, "orderBy", this.getOrderBys(), tabContent);
appendField(sb, "queryConcurrency", this.getQueryConcurrency(), tabContent);
appendField(sb, "columns", this.getColumns(), tabContent);
appendField(sb, "groupBys", this.getGroupBys(), tabContent);
appendField(sb, "strategy", this.getJoinStrategy(), tabContent);
appendField(sb, "executeOn", this.getDataNode(), tabContent);
// if(this.getThread()!=null)
// appendField(sb, "thread",
// this.getThread(), tabContent);
// appendField(sb, "requestID",
// this.getRequestID(), tabContent);
// appendField(sb, "subRequestID",
// this.getSubRequestID(), tabContent);
appendln(sb, tabContent + "left:");
sb.append(this.getLeftNode().toStringWithInden(inden + 2));
appendln(sb, tabContent + "right:");
sb.append(this.getRightNode().toStringWithInden(inden + 2));
return sb.toString();
}
}