package jef.database.jsqlparser;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import jef.database.dialect.DatabaseDialect;
import jef.database.jsqlparser.expression.Function;
import jef.database.jsqlparser.expression.LongValue;
import jef.database.jsqlparser.expression.operators.relational.ExpressionList;
import jef.database.jsqlparser.statement.select.Limit;
import jef.database.jsqlparser.statement.select.PlainSelect;
import jef.database.jsqlparser.statement.select.SelectExpressionItem;
import jef.database.jsqlparser.statement.select.SubSelect;
import jef.database.jsqlparser.statement.select.Union;
import jef.database.jsqlparser.visitor.Expression;
import jef.database.jsqlparser.visitor.SelectBody;
import jef.database.jsqlparser.visitor.SelectItem;
import jef.database.jsqlparser.visitor.ToCountDeParser;
import jef.database.query.SqlExpression;
public class SelectToCountWrapper extends PlainSelect{
private static final ExpressionList EXP_1=new ExpressionList(LongValue.L1);
private static final List<SelectItem> SELECT_1=Arrays.<SelectItem>asList(new SelectExpressionItem(LongValue.L1,"l"));
private SubSelect inner;
private boolean isDistinct;
private Limit removedLimit;
public SelectToCountWrapper(Union union){
//将Select部分重写为新的Count Function
Function count=new Function();
count.setName("count");
count.setAllColumns(true);
SelectExpressionItem countItem=new SelectExpressionItem();
countItem.setExpression(count);
countItem.setAlias("count");
this.selectItems=Arrays.<SelectItem>asList(countItem);
//将原来的Union部分套在SubSelect内。
inner=new SubSelect();
Union newUnion=new Union(union);
newUnion.setOrderBy(null);
inner.setSelectBody(newUnion);
inner.setAlias("t__cnt"); //为了兼容Derby,故给表一个别名
this.fromItem=inner;
}
public SelectToCountWrapper(PlainSelect select,DatabaseDialect profile){
isDistinct=select.getDistinct()!=null;
List<Expression> distinctToGroupBy=null;
if(isDistinct && select.getSelectItems().size()>1){//Distinct多个列
distinctToGroupBy=distinctItemToGroupItem(select);
}
if(select.isGroupBy() || distinctToGroupBy!=null){
Function count=new Function();
count.setName("count");
count.setParameters(EXP_1);
SelectExpressionItem countItem=new SelectExpressionItem();
countItem.setExpression(count);
countItem.setAlias("t__cnt");
this.selectItems=Arrays.<SelectItem>asList(countItem);
//将原来的Select部分套在SubSelect内。
PlainSelect innerSelect=new PlainSelect(select);
if(distinctToGroupBy!=null){
innerSelect.setDistinct(null);
innerSelect.setGroupByColumnReferences(distinctToGroupBy);
}
innerSelect.setOrderBy(null);
// List<SelectItem> ns=new ArrayList<SelectItem>();
// for(Expression exp: innerSelect.getGroupByColumnReferences()){
// SelectExpressionItem item=new SelectExpressionItem();
// item.setExpression(exp);
// ns.add(item);
// }
innerSelect.setSelectItems(SELECT_1);
inner=new SubSelect();
inner.setSelectBody(innerSelect);
inner.setAlias("t__cnt");//为了兼容Derby,故给表一个别名
this.fromItem=inner;
}else{
this.distinct=null; //特殊处理1 distinct去除
SelectItem convert=getSelectItem(select,profile);
this.selectItems=Arrays.asList(convert);//Select部分重写
this.top=select.getTop();
this.into=select.getInto();
this.fromItem=select.getFromItem();
this.joins=select.getJoins();
this.where=select.getWhere();
this.groupByColumnReferences=select.getGroupByColumnReferences();
this.having=select.getHaving();
removedLimit=select.getLimit();
//this.orderByElements=select.getOrderByElements(); //Order不要
}
}
private List<Expression> distinctItemToGroupItem(PlainSelect select) {
List<Expression> result=new ArrayList<Expression>();
for(SelectItem item:select.getSelectItems()){
if(item.isAllColumns()){
continue;
}
result.add(item.getAsSelectExpression().getExpression());//将
}
return result;
}
private SelectItem getSelectItem(PlainSelect select,DatabaseDialect profile) {
SelectExpressionItem result=new SelectExpressionItem();
StringBuilder sb=new StringBuilder(64);
ToCountDeParser.rewriteSelectItem(sb, select, profile);
result.setExpression(new SqlExpression(sb.toString()));
return result;
}
public SelectBody getInnerSelectBody(){
if(inner!=null){
return inner.getSelectBody();
}
return null;
}
public boolean isDistinct() {
return isDistinct;
}
public Limit getRemovedLimit() {
return removedLimit;
}
}