package com.taobao.tddl.optimizer.core.ast.build;
import java.util.LinkedList;
import java.util.List;
import com.taobao.tddl.optimizer.core.ASTNodeFactory;
import com.taobao.tddl.optimizer.core.ast.ASTNode;
import com.taobao.tddl.optimizer.core.ast.QueryTreeNode;
import com.taobao.tddl.optimizer.core.ast.query.QueryNode;
import com.taobao.tddl.optimizer.core.expression.IBooleanFilter;
import com.taobao.tddl.optimizer.core.expression.IColumn;
import com.taobao.tddl.optimizer.core.expression.IFilter.OPERATION;
import com.taobao.tddl.optimizer.core.expression.IFunction;
import com.taobao.tddl.optimizer.core.expression.ISelectable;
/**
* @since 5.0.0
*/
public class QueryNodeBuilder extends QueryTreeNodeBuilder {
public QueryNodeBuilder(QueryNode queryNode){
this.setNode(queryNode);
}
public QueryNode getNode() {
return (QueryNode) super.getNode();
}
public void build() {
for (ASTNode sub : this.getNode().getChildren()) {
sub.build();
}
if (!(this.getNode().getChild() instanceof QueryTreeNode)) {// 嵌套子类
return;
}
this.buildAlias();
this.buildSelected();
this.buildWhere();
this.buildGroupBy();
this.buildOrderBy();
if (this.getNode().getDataNode() == null) {
this.getNode().executeOn(this.getNode().getChild().getDataNode());
}
this.buildExistAggregate();
}
private void buildAlias() {
if (this.getNode().getAlias() == null) {
this.getNode().alias(this.getNode().getChild().getAlias());
}
}
public void buildSelected() {
buildSelectedFromSelectableObject();
}
private void buildSelectedFromSelectableObject() {
if (this.getNode().getColumnsSelected().isEmpty()) {
this.getNode()
.getColumnsSelected()
.add(ASTNodeFactory.getInstance().createColumn().setColumnName(IColumn.STAR));
}
// 如果有 * ,最后需要把*删掉
List<ISelectable> delete = new LinkedList();
for (ISelectable selected : getNode().getColumnsSelected()) {
if (selected.getColumnName().equals(IColumn.STAR)) {
delete.add(selected);
}
}
if (!delete.isEmpty()) {
this.getNode().getColumnsSelected().removeAll(delete);
}
for (ISelectable selected : delete) {
// 遇到*就把所有列再添加一遍
// select *,id这样的语法最后会有两个id列,mysql是这样的
QueryTreeNode child = (QueryTreeNode) this.getNode().getChild();
for (ISelectable selectedFromChild : child.getColumnsSelected()) {
if (selected.getTableName() != null
&& !selected.getTableName().equals(selectedFromChild.getTableName())) {
break;
}
IColumn newS = ASTNodeFactory.getInstance().createColumn();
if (child.getAlias() != null) {// sub alias
newS.setTableName(child.getAlias());
} else {
newS.setTableName(selectedFromChild.getTableName());
}
if (selectedFromChild.getAlias() == null) {
newS.setColumnName(selectedFromChild.getColumnName());
} else {
newS.setColumnName(selectedFromChild.getAlias());
}
getNode().getColumnsSelected().add(newS);// 允许多列
}
}
for (int i = 0; i < getNode().getColumnsSelected().size(); i++) {
getNode().getColumnsSelected().set(i, this.buildSelectable(getNode().getColumnsSelected().get(i)));
}
}
public ISelectable getSelectableFromChild(ISelectable c) {
if (IColumn.STAR.equals(c.getColumnName())) {
return c;
}
if (c instanceof IFunction) {
return c;
}
if (c instanceof IBooleanFilter && ((IBooleanFilter) c).getOperation().equals(OPERATION.CONSTANT)) {
return c;
}
return this.getColumnFromOtherNode(c, this.getNode().getChild());
}
}