package com.taobao.tddl.optimizer.core.ast.build;
import java.util.LinkedList;
import java.util.List;
import com.taobao.tddl.optimizer.OptimizerContext;
import com.taobao.tddl.optimizer.config.table.ColumnMeta;
import com.taobao.tddl.optimizer.config.table.IndexMeta;
import com.taobao.tddl.optimizer.core.ASTNodeFactory;
import com.taobao.tddl.optimizer.core.ast.query.KVIndexNode;
import com.taobao.tddl.optimizer.core.expression.IColumn;
import com.taobao.tddl.optimizer.core.expression.IFunction;
import com.taobao.tddl.optimizer.core.expression.ISelectable;
import com.taobao.tddl.optimizer.exceptions.OptimizerException;
import com.taobao.tddl.optimizer.utils.OptimizerUtils;
/**
* @since 5.0.0
*/
public class KVIndexNodeBuilder extends QueryTreeNodeBuilder {
public KVIndexNodeBuilder(KVIndexNode node){
this.setNode(node);
}
public KVIndexNode getNode() {
return (KVIndexNode) super.getNode();
}
public void build() {
this.buildIndex();
this.buildSelected();
this.buildGroupBy();
this.buildOrderBy();
this.buildWhere();
this.buildExistAggregate();
}
/**
* 構建列信息
*
* @param indexNode
*/
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 (IColumn.STAR.equals(selected.getColumnName())) {
delete.add(selected);
}
}
if (!delete.isEmpty()) {
this.getNode().getColumnsSelected().removeAll(delete);
// 遇到*就把所有列再添加一遍
// select *,id这样的语法最后会有两个id列,mysql是这样的
for (ColumnMeta cm : this.getNode().getIndex().getKeyColumns()) {
this.getNode()
.getColumnsSelected()
.add(OptimizerUtils.columnMetaToIColumn(cm, this.getNode().getIndexName()));
}
for (ColumnMeta cm : this.getNode().getIndex().getValueColumns()) {
this.getNode()
.getColumnsSelected()
.add(OptimizerUtils.columnMetaToIColumn(cm, this.getNode().getIndexName()));
}
}
for (int i = 0; i < getNode().getColumnsSelected().size(); i++) {
this.getNode().getColumnsSelected().set(i, this.buildSelectable(getNode().getColumnsSelected().get(i)));
}
}
/**
* 构建索引信息
*
* @param getNode ()
*/
public void buildIndex() {
String kvIndexName = getNode().getKvIndexName();
if (kvIndexName != null) {
IndexMeta index = OptimizerContext.getContext().getIndexManager().getIndexByName(kvIndexName);
if (index == null) {
throw new OptimizerException("index :" + kvIndexName + " is not found");
}
getNode().setIndex(index);
getNode().setTableMeta(OptimizerContext.getContext().getSchemaManager().getTable(index.getTableName()));
} else if (getNode().getIndex() == null) {
throw new OptimizerException("index is null");
}
}
public ISelectable getSelectableFromChild(ISelectable c) {
if (c.getTableName() != null) {
if ((!c.getTableName().equals(this.getNode().getIndexName()))
&& (!c.getTableName().equals(this.getNode().getAlias()))) {
return null;
}
}
if (IColumn.STAR.equals(c.getColumnName())) {
return c;
}
if (c instanceof IFunction) {
c.setTableName(this.getNode().getIndexName());
return c;
}
return this.getSelectableFromChild(c.getColumnName());
}
private ISelectable getSelectableFromChild(String columnName) {
ColumnMeta cm = this.getNode().getIndex().getColumnMeta(columnName);
if (cm == null) {
return null;
}
return OptimizerUtils.columnMetaToIColumn(cm, getNode().getIndexName());
}
}