package io.mycat.route.parser.druid;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;
import com.alibaba.druid.sql.ast.expr.SQLAllExpr;
import com.alibaba.druid.sql.ast.expr.SQLAnyExpr;
import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLExistsExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
import com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
import com.alibaba.druid.sql.ast.expr.SQLSomeExpr;
import com.alibaba.druid.sql.ast.expr.SQLValuableExpr;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlHintStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.stat.TableStat.Column;
import com.alibaba.druid.stat.TableStat.Condition;
import com.alibaba.druid.stat.TableStat.Mode;
import com.alibaba.druid.stat.TableStat.Relationship;

import io.mycat.route.util.RouterUtil;

/**
 * Druid解析器中用来从ast语法中提取表名、条件、字段等的vistor
 * @author wang.dw
 *
 */
public class MycatSchemaStatVisitor extends MySqlSchemaStatVisitor {
	private boolean hasOrCondition = false;
	private List<WhereUnit> whereUnits = new ArrayList<WhereUnit>();
	private List<WhereUnit> storedwhereUnits = new ArrayList<>();
    private Queue<SQLSelect> subQuerys = new LinkedList<>();  //子查询集合
	private boolean hasChange = false; // 是否有改写sql
	private boolean subqueryRelationOr = false;   //子查询存在关联条件的情况下,是否有 or 条件
	
	private void reset() {
		this.conditions.clear();
		this.whereUnits.clear();
		this.hasOrCondition = false;
	}
	
	public List<WhereUnit> getWhereUnits() {
		return whereUnits;
	}

	public boolean hasOrCondition() {
		return hasOrCondition;
	}
	
    @Override
    public boolean visit(SQLSelectStatement x) {
        setAliasMap();
//        getAliasMap().put("DUAL", null);

        return true;
    }

    @Override
    public boolean visit(SQLBetweenExpr x) {
        String begin = null;
        if(x.beginExpr instanceof SQLCharExpr)
        {
            begin= (String) ( (SQLCharExpr)x.beginExpr).getValue();
        }  else {
            begin = x.beginExpr.toString();
        }
        String end = null;
        if(x.endExpr instanceof SQLCharExpr)
        {
            end= (String) ( (SQLCharExpr)x.endExpr).getValue();
        }  else {
            end = x.endExpr.toString();
        }
        Column column = getColumn(x);
        if (column == null) {
            return true;
        }

        Condition condition = null;
        for (Condition item : this.getConditions()) {
            if (item.getColumn().equals(column) && item.getOperator().equals("between")) {
                condition = item;
                break;
            }
        }

        if (condition == null) {
            condition = new Condition();
            condition.setColumn(column);
            condition.setOperator("between");
            this.conditions.add(condition);
        }


        condition.getValues().add(begin);
        condition.getValues().add(end);


        return true;
    }

    @Override
    protected Column getColumn(SQLExpr expr) {
        Map<String, String> aliasMap = getAliasMap();
        if (aliasMap == null) {
            return null;
        }

        if (expr instanceof SQLPropertyExpr) {
            SQLExpr owner = ((SQLPropertyExpr) expr).getOwner();
            String column = ((SQLPropertyExpr) expr).getName();

            if (owner instanceof SQLIdentifierExpr) {
                String tableName = ((SQLIdentifierExpr) owner).getName();
                String table = tableName;
                if (aliasMap.containsKey(table)) {
                    table = aliasMap.get(table);
                }

                if (variants.containsKey(table)) {
                    return null;
                }

                if (table != null) {
                    return new Column(table, column);
                }

                return handleSubQueryColumn(tableName, column);
            }

            return null;
        }

        if (expr instanceof SQLIdentifierExpr) {
            Column attrColumn = (Column) expr.getAttribute(ATTR_COLUMN);
            if (attrColumn != null) {
                return attrColumn;
            }

            String column = ((SQLIdentifierExpr) expr).getName();
            String table = getCurrentTable();
            if (table != null && aliasMap.containsKey(table)) {
                table = aliasMap.get(table);
                if (table == null) {
                    return null;
                }
            }

            if (table != null) {
                return new Column(table, column);
            }

            if (variants.containsKey(column)) {
                return null;
            }

            return new Column("UNKNOWN", column);
        }

        if(expr instanceof SQLBetweenExpr) {
            SQLBetweenExpr betweenExpr = (SQLBetweenExpr)expr;

            if(betweenExpr.getTestExpr() != null) {
                String tableName = null;
                String column = null;
                if(betweenExpr.getTestExpr() instanceof SQLPropertyExpr) {//字段带别名的
                    tableName = ((SQLIdentifierExpr)((SQLPropertyExpr) betweenExpr.getTestExpr()).getOwner()).getName();
                    column = ((SQLPropertyExpr) betweenExpr.getTestExpr()).getName();
					SQLObject query = this.subQueryMap.get(tableName);
					if(query == null) {
						if (aliasMap.containsKey(tableName)) {
							tableName = aliasMap.get(tableName);
						}
						return new Column(tableName, column);
					}
                    return handleSubQueryColumn(tableName, column);
                } else if(betweenExpr.getTestExpr() instanceof SQLIdentifierExpr) {
                    column = ((SQLIdentifierExpr) betweenExpr.getTestExpr()).getName();
                    //字段不带别名的,此处如果是多表,容易出现ambiguous,
                    //不知道这个字段是属于哪个表的,fdbparser用了defaultTable,即join语句的leftTable
                    tableName = getOwnerTableName(betweenExpr,column);
                }
                String table = tableName;
                if (aliasMap.containsKey(table)) {
                    table = aliasMap.get(table);
                }

                if (variants.containsKey(table)) {
                    return null;
                }

                if (table != null&&!"".equals(table)) {
                    return new Column(table, column);
                }
            }


        }
        return null;
    }

    /**
     * 从between语句中获取字段所属的表名。
     * 对于容易出现ambiguous的(字段不知道到底属于哪个表),实际应用中必须使用别名来避免歧义
     * @param betweenExpr
     * @param column
     * @return
     */
    private String getOwnerTableName(SQLBetweenExpr betweenExpr,String column) {
        if(tableStats.size() == 1) {//只有一个表,直接返回这一个表名
            return tableStats.keySet().iterator().next().getName();
        } else if(tableStats.size() == 0) {//一个表都没有,返回空串
            return "";
        } else {//多个表名
            for (Column col : columns.keySet())
            {
                if(col.getName().equals(column)) {
                    return col.getTable();
                }
            }
//            for(Column col : columns) {//从columns中找表名
//                if(col.getName().equals(column)) {
//                    return col.getTable();
//                }
//            }

            //前面没找到表名的,自己从parent中解析

            SQLObject parent = betweenExpr.getParent();
            if(parent instanceof SQLBinaryOpExpr)
            {
                parent=parent.getParent();
            }

            if(parent instanceof MySqlSelectQueryBlock) {
                MySqlSelectQueryBlock select = (MySqlSelectQueryBlock) parent;
                if(select.getFrom() instanceof SQLJoinTableSource) {//多表连接
                    SQLJoinTableSource joinTableSource = (SQLJoinTableSource)select.getFrom();
                    return joinTableSource.getLeft().toString();//将left作为主表,此处有不严谨处,但也是实在没有办法,如果要准确,字段前带表名或者表的别名即可
                } else if(select.getFrom() instanceof SQLExprTableSource) {//单表
                    return select.getFrom().toString();
                }
            }
            else if(parent instanceof SQLUpdateStatement) {
                SQLUpdateStatement update = (SQLUpdateStatement) parent;
                return update.getTableName().getSimpleName();
            } else if(parent instanceof SQLDeleteStatement) {
                SQLDeleteStatement delete = (SQLDeleteStatement) parent;
                return delete.getTableName().getSimpleName();
            } else {
                
            }
        }
        return "";
    }
    
    private void setSubQueryRelationOrFlag(SQLExprImpl x){
    	MycatSubQueryVisitor subQueryVisitor = new MycatSubQueryVisitor();
    	x.accept(subQueryVisitor);
    	if(subQueryVisitor.isRelationOr()){
    		subqueryRelationOr = true;
    	}
    }
    
    /*
     * 子查询
     * (non-Javadoc)
     * @see com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter#visit(com.alibaba.druid.sql.ast.expr.SQLQueryExpr)
     */
    @Override
    public boolean visit(SQLQueryExpr x) {
    	setSubQueryRelationOrFlag(x);
    	addSubQuerys(x.getSubQuery());
    	return super.visit(x);
    }
    /*
     * (non-Javadoc)
     * @see com.alibaba.druid.sql.visitor.SchemaStatVisitor#visit(com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource)
     */
    @Override
    public boolean visit(SQLSubqueryTableSource x){
    	addSubQuerys(x.getSelect());
    	return super.visit(x);
    }
    
    /*
     * (non-Javadoc)
     * @see com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter#visit(com.alibaba.druid.sql.ast.expr.SQLExistsExpr)
     */
    @Override
    public boolean visit(SQLExistsExpr x) {
    	setSubQueryRelationOrFlag(x);
    	addSubQuerys(x.getSubQuery());
    	return super.visit(x);
    }
    
    @Override
    public boolean visit(SQLInListExpr x) {
    	return super.visit(x);
    }
    
    /*
     *  对 in 子查询的处理
     * (non-Javadoc)
     * @see com.alibaba.druid.sql.visitor.SchemaStatVisitor#visit(com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr)
     */
    @Override
    public boolean visit(SQLInSubQueryExpr x) {
    	setSubQueryRelationOrFlag(x);
    	addSubQuerys(x.getSubQuery());
    	return super.visit(x);
    }
    
    /* 
     *  遇到 all 将子查询改写成  SELECT MAX(name) FROM subtest1
     *  例如:
     *        select * from subtest where id > all (select name from subtest1);
     *    		>/>= all ----> >/>= max
     *    		</<= all ----> </<= min
     *    		<>   all ----> not in
     *          =    all ----> id = 1 and id = 2
     *          other  不改写
     */    
    @Override
    public boolean visit(SQLAllExpr x) {
    	setSubQueryRelationOrFlag(x);
    	
    	List<SQLSelectItem> itemlist = ((SQLSelectQueryBlock)(x.getSubQuery().getQuery())).getSelectList();
    	SQLExpr sexpr = itemlist.get(0).getExpr();
    	
		if(x.getParent() instanceof SQLBinaryOpExpr){
			SQLBinaryOpExpr parentExpr = (SQLBinaryOpExpr)x.getParent();
			SQLAggregateExpr saexpr = null;
			switch (parentExpr.getOperator()) {
			case GreaterThan:
			case GreaterThanOrEqual:
			case NotLessThan:
				this.hasChange = true;
				if(sexpr instanceof SQLIdentifierExpr 
						|| (sexpr instanceof SQLPropertyExpr&&((SQLPropertyExpr)sexpr).getOwner() instanceof SQLIdentifierExpr)){
					saexpr = new SQLAggregateExpr("MAX");
					saexpr.getArguments().add(sexpr);
	        		saexpr.setParent(itemlist.get(0));
	        		itemlist.get(0).setExpr(saexpr);
				}
				SQLQueryExpr maxSubQuery = new SQLQueryExpr(x.getSubQuery());
        		x.getSubQuery().setParent(x.getParent());
        		// 生成新的SQLQueryExpr 替换当前 SQLAllExpr 节点
            	if(x.getParent() instanceof SQLBinaryOpExpr){
            		if(((SQLBinaryOpExpr)x.getParent()).getLeft().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setLeft(maxSubQuery);
            		}else if(((SQLBinaryOpExpr)x.getParent()).getRight().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setRight(maxSubQuery);
            		}
            	}
            	addSubQuerys(x.getSubQuery());
            	return super.visit(x.getSubQuery());
			case LessThan:
			case LessThanOrEqual:
			case NotGreaterThan:
				this.hasChange = true;
				if(sexpr instanceof SQLIdentifierExpr 
						|| (sexpr instanceof SQLPropertyExpr&&((SQLPropertyExpr)sexpr).getOwner() instanceof SQLIdentifierExpr)){
					saexpr = new SQLAggregateExpr("MIN");
					saexpr.getArguments().add(sexpr);
	        		saexpr.setParent(itemlist.get(0));
	        		itemlist.get(0).setExpr(saexpr);
	        		
	            	x.subQuery.setParent(x.getParent());
				}
				// 生成新的SQLQueryExpr 替换当前 SQLAllExpr 节点
            	SQLQueryExpr minSubQuery = new SQLQueryExpr(x.getSubQuery());
            	if(x.getParent() instanceof SQLBinaryOpExpr){
            		if(((SQLBinaryOpExpr)x.getParent()).getLeft().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setLeft(minSubQuery);
            		}else if(((SQLBinaryOpExpr)x.getParent()).getRight().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setRight(minSubQuery);
            		}
            	}
            	addSubQuerys(x.getSubQuery());
            	return super.visit(x.getSubQuery());
			 case LessThanOrGreater:
			 case NotEqual:
				this.hasChange = true;
				SQLInSubQueryExpr notInSubQueryExpr = new SQLInSubQueryExpr(x.getSubQuery());
				x.getSubQuery().setParent(notInSubQueryExpr);
				notInSubQueryExpr.setNot(true);
				// 生成新的SQLQueryExpr 替换当前 SQLAllExpr 节点
				if(x.getParent() instanceof SQLBinaryOpExpr){
					SQLBinaryOpExpr xp = (SQLBinaryOpExpr)x.getParent();
					
					if(xp.getLeft().equals(x)){
						notInSubQueryExpr.setExpr(xp.getRight());
					}else if(xp.getRight().equals(x)){
						notInSubQueryExpr.setExpr(xp.getLeft());
					}
					
					if(xp.getParent() instanceof MySqlSelectQueryBlock){
						((MySqlSelectQueryBlock)xp.getParent()).setWhere(notInSubQueryExpr);
					}else if(xp.getParent() instanceof SQLBinaryOpExpr){
						SQLBinaryOpExpr pp = ((SQLBinaryOpExpr)xp.getParent());
						if(pp.getLeft().equals(xp)){
							pp.setLeft(notInSubQueryExpr);
						}else if(pp.getRight().equals(xp)){
							pp.setRight(notInSubQueryExpr);
						}
					}
	            }
				addSubQuerys(x.getSubQuery());
	            return super.visit(notInSubQueryExpr);
			 default:
				break;
			}
		}
		addSubQuerys(x.getSubQuery());
    	return super.visit(x);
    }
    
    /* 
     *  遇到 some 将子查询改写成  SELECT MIN(name) FROM subtest1
     *  例如:
     *        select * from subtest where id > some (select name from subtest1);
     *    >/>= some ----> >/>= min
     *    </<= some ----> </<= max
     *    <>   some ----> not in
     *    =    some ----> in
     *    other  不改写
     */
    @Override
    public boolean visit(SQLSomeExpr x) {
    	
    	setSubQueryRelationOrFlag(x);
    	
    	List<SQLSelectItem> itemlist = ((SQLSelectQueryBlock)(x.getSubQuery().getQuery())).getSelectList();
    	SQLExpr sexpr = itemlist.get(0).getExpr();
    	
		if(x.getParent() instanceof SQLBinaryOpExpr){
			SQLBinaryOpExpr parentExpr = (SQLBinaryOpExpr)x.getParent();
			SQLAggregateExpr saexpr = null;
			switch (parentExpr.getOperator()) {
			case GreaterThan:
			case GreaterThanOrEqual:
			case NotLessThan:
				this.hasChange = true;
				if(sexpr instanceof SQLIdentifierExpr 
						|| (sexpr instanceof SQLPropertyExpr&&((SQLPropertyExpr)sexpr).getOwner() instanceof SQLIdentifierExpr)){
					saexpr = new SQLAggregateExpr("MIN");
					saexpr.getArguments().add(sexpr);
	        		saexpr.setParent(itemlist.get(0));
	        		itemlist.get(0).setExpr(saexpr);
				}
				SQLQueryExpr maxSubQuery = new SQLQueryExpr(x.getSubQuery());
        		x.getSubQuery().setParent(maxSubQuery);
        		// 生成新的SQLQueryExpr 替换当前 SQLAllExpr 节点
            	if(x.getParent() instanceof SQLBinaryOpExpr){
            		if(((SQLBinaryOpExpr)x.getParent()).getLeft().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setLeft(maxSubQuery);
            		}else if(((SQLBinaryOpExpr)x.getParent()).getRight().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setRight(maxSubQuery);
            		}
            	}
            	addSubQuerys(x.getSubQuery());
            	return super.visit(x.getSubQuery());
			case LessThan:
			case LessThanOrEqual:
			case NotGreaterThan:
				this.hasChange = true;
				if(sexpr instanceof SQLIdentifierExpr 
						|| (sexpr instanceof SQLPropertyExpr&&((SQLPropertyExpr)sexpr).getOwner() instanceof SQLIdentifierExpr)){
					saexpr = new SQLAggregateExpr("MAX");
					saexpr.getArguments().add(sexpr);
	        		saexpr.setParent(itemlist.get(0));
	        		itemlist.get(0).setExpr(saexpr);
				}
				// 生成新的SQLQueryExpr 替换当前 SQLAllExpr 节点
            	SQLQueryExpr minSubQuery = new SQLQueryExpr(x.getSubQuery());
        		x.getSubQuery().setParent(minSubQuery);
            	
            	if(x.getParent() instanceof SQLBinaryOpExpr){
            		if(((SQLBinaryOpExpr)x.getParent()).getLeft().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setLeft(minSubQuery);
            		}else if(((SQLBinaryOpExpr)x.getParent()).getRight().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setRight(minSubQuery);
            		}
            	}
            	addSubQuerys(x.getSubQuery());
            	return super.visit(x.getSubQuery());
			 case LessThanOrGreater:
			 case NotEqual:
				 this.hasChange = true;
					SQLInSubQueryExpr notInSubQueryExpr = new SQLInSubQueryExpr(x.getSubQuery());
					x.getSubQuery().setParent(notInSubQueryExpr);
					notInSubQueryExpr.setNot(true);
					// 生成新的SQLQueryExpr 替换当前 SQLAllExpr 节点
					if(x.getParent() instanceof SQLBinaryOpExpr){
						SQLBinaryOpExpr xp = (SQLBinaryOpExpr)x.getParent();
						
						if(xp.getLeft().equals(x)){
							notInSubQueryExpr.setExpr(xp.getRight());
						}else if(xp.getRight().equals(x)){
							notInSubQueryExpr.setExpr(xp.getLeft());
						}
						
						if(xp.getParent() instanceof MySqlSelectQueryBlock){
							((MySqlSelectQueryBlock)xp.getParent()).setWhere(notInSubQueryExpr);
						}else if(xp.getParent() instanceof SQLBinaryOpExpr){
							SQLBinaryOpExpr pp = ((SQLBinaryOpExpr)xp.getParent());
							if(pp.getLeft().equals(xp)){
								pp.setLeft(notInSubQueryExpr);
							}else if(pp.getRight().equals(xp)){
								pp.setRight(notInSubQueryExpr);
							}
						}
		            }
					addSubQuerys(x.getSubQuery());
		            return super.visit(notInSubQueryExpr);
			 case Equality:
				 this.hasChange = true;
				SQLInSubQueryExpr inSubQueryExpr = new SQLInSubQueryExpr(x.getSubQuery());
				x.getSubQuery().setParent(inSubQueryExpr);
				inSubQueryExpr.setNot(false);
				// 生成新的SQLQueryExpr 替换当前 SQLAllExpr 节点
				if(x.getParent() instanceof SQLBinaryOpExpr){
					SQLBinaryOpExpr xp = (SQLBinaryOpExpr)x.getParent();
					
					if(xp.getLeft().equals(x)){
						inSubQueryExpr.setExpr(xp.getRight());
					}else if(xp.getRight().equals(x)){
						inSubQueryExpr.setExpr(xp.getLeft());
					}
					
					if(xp.getParent() instanceof MySqlSelectQueryBlock){
						((MySqlSelectQueryBlock)xp.getParent()).setWhere(inSubQueryExpr);
					}else if(xp.getParent() instanceof SQLBinaryOpExpr){
						SQLBinaryOpExpr pp = ((SQLBinaryOpExpr)xp.getParent());
						if(pp.getLeft().equals(xp)){
							pp.setLeft(inSubQueryExpr);
						}else if(pp.getRight().equals(xp)){
							pp.setRight(inSubQueryExpr);
						}
					}
	            }
				addSubQuerys(x.getSubQuery());
	            return super.visit(inSubQueryExpr);
			 default:
				break;
			}
		}
		addSubQuerys(x.getSubQuery());
    	return super.visit(x);
    }

    /* 
     *  遇到 any 将子查询改写成  SELECT MIN(name) FROM subtest1
     *  例如:
     *    select * from subtest where id oper any (select name from subtest1);
     *    >/>= any ----> >/>= min
     *    </<= any ----> </<= max
     *    <>   any ----> not in
     *    =    some ----> in
     *    other  不改写
     */
    @Override
    public boolean visit(SQLAnyExpr x) {
    	
    	setSubQueryRelationOrFlag(x);
    	
    	List<SQLSelectItem> itemlist = ((SQLSelectQueryBlock)(x.getSubQuery().getQuery())).getSelectList();
    	SQLExpr sexpr = itemlist.get(0).getExpr();
    	
		if(x.getParent() instanceof SQLBinaryOpExpr){
			SQLBinaryOpExpr parentExpr = (SQLBinaryOpExpr)x.getParent();
			SQLAggregateExpr saexpr = null;
			switch (parentExpr.getOperator()) {
			case GreaterThan:
			case GreaterThanOrEqual:
			case NotLessThan:
				this.hasChange = true;
				if(sexpr instanceof SQLIdentifierExpr 
						|| (sexpr instanceof SQLPropertyExpr&&((SQLPropertyExpr)sexpr).getOwner() instanceof SQLIdentifierExpr)){
					saexpr = new SQLAggregateExpr("MIN");
					saexpr.getArguments().add(sexpr);
	        		saexpr.setParent(itemlist.get(0));
	        		itemlist.get(0).setExpr(saexpr);
				}
				SQLQueryExpr maxSubQuery = new SQLQueryExpr(x.getSubQuery());
        		x.getSubQuery().setParent(maxSubQuery);
				// 生成新的SQLQueryExpr 替换当前 SQLAllExpr 节点
            	if(x.getParent() instanceof SQLBinaryOpExpr){
            		if(((SQLBinaryOpExpr)x.getParent()).getLeft().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setLeft(maxSubQuery);
            		}else if(((SQLBinaryOpExpr)x.getParent()).getRight().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setRight(maxSubQuery);
            		}
            	}
            	addSubQuerys(x.getSubQuery());
            	return super.visit(x.getSubQuery());
			case LessThan:
			case LessThanOrEqual:
			case NotGreaterThan:
				this.hasChange = true;
				if(sexpr instanceof SQLIdentifierExpr 
						|| (sexpr instanceof SQLPropertyExpr&&((SQLPropertyExpr)sexpr).getOwner() instanceof SQLIdentifierExpr)){
					saexpr = new SQLAggregateExpr("MAX");
					saexpr.getArguments().add(sexpr);
	        		saexpr.setParent(itemlist.get(0));
	        		itemlist.get(0).setExpr(saexpr);
				}
				// 生成新的SQLQueryExpr 替换当前 SQLAllExpr 节点
            	SQLQueryExpr minSubQuery = new SQLQueryExpr(x.getSubQuery());
            	x.subQuery.setParent(minSubQuery);
            	if(x.getParent() instanceof SQLBinaryOpExpr){
            		if(((SQLBinaryOpExpr)x.getParent()).getLeft().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setLeft(minSubQuery);
            		}else if(((SQLBinaryOpExpr)x.getParent()).getRight().equals(x)){
            			((SQLBinaryOpExpr)x.getParent()).setRight(minSubQuery);
            		}
            	}
            	addSubQuerys(x.getSubQuery());
            	return super.visit(x.getSubQuery());
			 case LessThanOrGreater:
			 case NotEqual:
				 this.hasChange = true;
					SQLInSubQueryExpr notInSubQueryExpr = new SQLInSubQueryExpr(x.getSubQuery());
					x.getSubQuery().setParent(notInSubQueryExpr);
					notInSubQueryExpr.setNot(true);
					// 生成新的SQLQueryExpr 替换当前 SQLAllExpr 节点
					if(x.getParent() instanceof SQLBinaryOpExpr){
						SQLBinaryOpExpr xp = (SQLBinaryOpExpr)x.getParent();
						
						if(xp.getLeft().equals(x)){
							notInSubQueryExpr.setExpr(xp.getRight());
						}else if(xp.getRight().equals(x)){
							notInSubQueryExpr.setExpr(xp.getLeft());
						}
						
						if(xp.getParent() instanceof MySqlSelectQueryBlock){
							((MySqlSelectQueryBlock)xp.getParent()).setWhere(notInSubQueryExpr);
						}else if(xp.getParent() instanceof SQLBinaryOpExpr){
							SQLBinaryOpExpr pp = ((SQLBinaryOpExpr)xp.getParent());
							if(pp.getLeft().equals(xp)){
								pp.setLeft(notInSubQueryExpr);
							}else if(pp.getRight().equals(xp)){
								pp.setRight(notInSubQueryExpr);
							}
						}
		            }
					addSubQuerys(x.getSubQuery());
		            return super.visit(notInSubQueryExpr);
			 case Equality:
				 this.hasChange = true;
				SQLInSubQueryExpr inSubQueryExpr = new SQLInSubQueryExpr(x.getSubQuery());
				x.getSubQuery().setParent(inSubQueryExpr);
				inSubQueryExpr.setNot(false);
				// 生成新的SQLQueryExpr 替换当前 SQLAllExpr 节点
				if(x.getParent() instanceof SQLBinaryOpExpr){
					SQLBinaryOpExpr xp = (SQLBinaryOpExpr)x.getParent();
					
					if(xp.getLeft().equals(x)){
						inSubQueryExpr.setExpr(xp.getRight());
					}else if(xp.getRight().equals(x)){
						inSubQueryExpr.setExpr(xp.getLeft());
					}
					
					if(xp.getParent() instanceof MySqlSelectQueryBlock){
						((MySqlSelectQueryBlock)xp.getParent()).setWhere(inSubQueryExpr);
					}else if(xp.getParent() instanceof SQLBinaryOpExpr){
						SQLBinaryOpExpr pp = ((SQLBinaryOpExpr)xp.getParent());
						if(pp.getLeft().equals(xp)){
							pp.setLeft(inSubQueryExpr);
						}else if(pp.getRight().equals(xp)){
							pp.setRight(inSubQueryExpr);
						}
					}
	            }
				addSubQuerys(x.getSubQuery());
	            return super.visit(inSubQueryExpr);
			 default:
				break;
			}
		}
		addSubQuerys(x.getSubQuery());
    	return super.visit(x);
    }
    
    @Override
	public boolean visit(SQLBinaryOpExpr x) {
        x.getLeft().setParent(x);
        x.getRight().setParent(x);
        
        /*
         * fix bug 当 selectlist 存在多个子查询时, 主表没有别名的情况下.主表的查询条件 被错误的附加到子查询上.
         *  eg. select (select id from subtest2 where id = 1), (select id from subtest3 where id = 2) from subtest1 where id =4;
         *  像这样的子查询, subtest1 的 过滤条件  id = 4 .  被 加入到  subtest3 上. 加别名的情况下正常,不加别名,就会存在这个问题.
         *  这里设置好操作的是哪张表后,再进行判断.
         */
        String currenttable = x.getParent()==null?null: (String) x.getParent().getAttribute(SchemaStatVisitor.ATTR_TABLE);
        if(currenttable!=null){
        	this.setCurrentTable(currenttable);
        }
        
        switch (x.getOperator()) {
            case Equality:
            case LessThanOrEqualOrGreaterThan:
            case Is:
            case IsNot:
            case GreaterThan:
            case GreaterThanOrEqual:
            case LessThan:
            case LessThanOrEqual:
            case NotLessThan:
            case LessThanOrGreater:
			case NotEqual:
			case NotGreaterThan:
                handleCondition(x.getLeft(), x.getOperator().name, x.getRight());
                handleCondition(x.getRight(), x.getOperator().name, x.getLeft());
                handleRelationship(x.getLeft(), x.getOperator().name, x.getRight());
                break;
            case BooleanOr:
            	//永真条件,where条件抛弃
            	if(!RouterUtil.isConditionAlwaysTrue(x)) {
            		hasOrCondition = true;
            		
            		WhereUnit whereUnit = null;
            		if(conditions.size() > 0) {
            			whereUnit = new WhereUnit();
            			whereUnit.setFinishedParse(true);
            			whereUnit.addOutConditions(getConditions());
            			WhereUnit innerWhereUnit = new WhereUnit(x);
            			whereUnit.addSubWhereUnit(innerWhereUnit);
            		} else {
            			whereUnit = new WhereUnit(x);
            			whereUnit.addOutConditions(getConditions());
            		}
            		whereUnits.add(whereUnit);
            	}
            	return false;
            case Like:
            case NotLike:
            default:
                break;
        }
        return true;
    }
	
	/**
	 * 分解条件
	 */
	public List<List<Condition>> splitConditions() {
		//按照or拆分
		for(WhereUnit whereUnit : whereUnits) {
			splitUntilNoOr(whereUnit);
		}
		
		this.storedwhereUnits.addAll(whereUnits);
		
		loopFindSubWhereUnit(whereUnits);
		
		//拆分后的条件块解析成Condition列表
		for(WhereUnit whereUnit : storedwhereUnits) {
			this.getConditionsFromWhereUnit(whereUnit);
		}
		
		//多个WhereUnit组合:多层集合的组合
		return mergedConditions();
	}
	
	/**
	 * 循环寻找子WhereUnit(实际是嵌套的or)
	 * @param whereUnitList
	 */
	private void loopFindSubWhereUnit(List<WhereUnit> whereUnitList) {
		List<WhereUnit> subWhereUnits = new ArrayList<WhereUnit>();
		for(WhereUnit whereUnit : new ArrayList<>(whereUnitList)) {
			if(whereUnit.getSplitedExprList().size() > 0) {
				List<SQLExpr> removeSplitedList = new ArrayList<SQLExpr>();
				for(SQLExpr sqlExpr : whereUnit.getSplitedExprList()) {
					reset();
					if(isExprHasOr(sqlExpr)) {
						removeSplitedList.add(sqlExpr);
						WhereUnit subWhereUnit = this.whereUnits.get(0);
						splitUntilNoOr(subWhereUnit);
						whereUnit.addSubWhereUnit(subWhereUnit);
						subWhereUnits.add(subWhereUnit);
					} else {
						this.conditions.clear();
					}
				}
				if(removeSplitedList.size() > 0) {
					whereUnit.getSplitedExprList().removeAll(removeSplitedList);
				}
			}
			subWhereUnits.addAll(whereUnit.getSubWhereUnit());
		}
		if(subWhereUnits.size() > 0) {
			loopFindSubWhereUnit(subWhereUnits);
		}
	}
	
	private boolean isExprHasOr(SQLExpr expr) {
		expr.accept(this);
		return hasOrCondition;
	}
	
	private List<List<Condition>> mergedConditions() {
		if(storedwhereUnits.size() == 0) {
			return new ArrayList<List<Condition>>();
		}
		for(WhereUnit whereUnit : storedwhereUnits) {
			mergeOneWhereUnit(whereUnit);
		}
		return getMergedConditionList(storedwhereUnits);
		
	}
	
	/**
	 * 一个WhereUnit内递归
	 * @param whereUnit
	 */
	private void mergeOneWhereUnit(WhereUnit whereUnit) {
		if(whereUnit.getSubWhereUnit().size() > 0) {
			for(WhereUnit sub : whereUnit.getSubWhereUnit()) {
				mergeOneWhereUnit(sub);
			}
			
			if(whereUnit.getSubWhereUnit().size() > 1) {
				List<List<Condition>> mergedConditionList = getMergedConditionList(whereUnit.getSubWhereUnit());
				if(whereUnit.getOutConditions().size() > 0) {
					for(int i = 0; i < mergedConditionList.size() ; i++) {
						mergedConditionList.get(i).addAll(whereUnit.getOutConditions());
					}
				}
				whereUnit.setConditionList(mergedConditionList);
			} else if(whereUnit.getSubWhereUnit().size() == 1) {
				if(whereUnit.getOutConditions().size() > 0 && whereUnit.getSubWhereUnit().get(0).getConditionList().size() > 0) {
					for(int i = 0; i < whereUnit.getSubWhereUnit().get(0).getConditionList().size() ; i++) {
						whereUnit.getSubWhereUnit().get(0).getConditionList().get(i).addAll(whereUnit.getOutConditions());
					}
				}
				whereUnit.getConditionList().addAll(whereUnit.getSubWhereUnit().get(0).getConditionList());
			}
		} else {
			//do nothing
		}
	}
	
	/**
	 * 条件合并:多个WhereUnit中的条件组合
	 * @return
	 */
	private List<List<Condition>> getMergedConditionList(List<WhereUnit> whereUnitList) {
		List<List<Condition>> mergedConditionList = new ArrayList<List<Condition>>();
		if(whereUnitList.size() == 0) {
			return mergedConditionList; 
		}
		mergedConditionList.addAll(whereUnitList.get(0).getConditionList());
		
		for(int i = 1; i < whereUnitList.size(); i++) {
			mergedConditionList = merge(mergedConditionList, whereUnitList.get(i).getConditionList());
		}
		return mergedConditionList;
	}
	
	/**
	 * 两个list中的条件组合
	 * @param list1
	 * @param list2
	 * @return
	 */
	    private List<List<Condition>> merge(List<List<Condition>> list1, List<List<Condition>> list2) {
        if(list1.size() == 0) {
            return list2;
        } else if (list2.size() == 0) {
            return list1;
        }
        
		List<List<Condition>> retList = new ArrayList<List<Condition>>();
		for(int i = 0; i < list1.size(); i++) {
			for(int j = 0; j < list2.size(); j++) {
//				List<Condition> listTmp = new ArrayList<Condition>();
//				listTmp.addAll(list1.get(i));
//				listTmp.addAll(list2.get(j));
//				retList.add(listTmp);
			    /**
		         * 单纯做笛卡尔积运算,会导致非常多不必要的条件列表,</br>
		         * 当whereUnit和条件相对多时,会急剧增长条件列表项,内存直线上升,导致假死状态</br>
		         * 因此,修改算法为 </br>
		         * 1、先合并两个条件列表的元素为一个条件列表</br>
		         * 2、计算合并后的条件列表,在结果retList中:</br>
		         * &nbsp;2-1、如果当前的条件列表 是 另外一个条件列表的 超集,更新,并标识已存在</br>
		         * &nbsp;2-2、如果当前的条件列表 是 另外一个条件列表的 子集,标识已存在</br>
		         * 3、最后,如果被标识不存在,加入结果retList,否则丢弃。</br>
		         * 
		         * @author SvenAugustus
		         */
  			    // 合并两个条件列表的元素为一个条件列表
                List<Condition> listTmp = mergeSqlConditionList(list1.get(i), list2.get(j));
      
                // 判定当前的条件列表 是否 另外一个条件列表的 子集
                boolean exists = false;
                Iterator<List<Condition>> it = retList.iterator();
                while (it.hasNext()) {
                  List<Condition> result = (List<Condition>) it.next();
                  if (result != null && listTmp != null && listTmp.size() > result.size()) {
                    // 如果当前的条件列表 是 另外一个条件列表的 超集,更新,并标识已存在
                    if (sqlConditionListInOther(result, listTmp)) {
                      result.clear();
                      result.addAll(listTmp);
                      exists = true;
                      break;
                    }
                  } else {
                    // 如果当前的条件列表 是 另外一个条件列表的 子集,标识已存在
                    if (sqlConditionListInOther(listTmp, result)) {
                      exists = true;
                      break;
                    }
                  }
                }
                if (!exists) {// 被标识不存在,加入
                  retList.add(listTmp);
                } // 否则丢弃
			}
		}
        return retList;
    }
	
	private void getConditionsFromWhereUnit(WhereUnit whereUnit) {
		List<List<Condition>> retList = new ArrayList<List<Condition>>();
		//or语句外层的条件:如where condition1 and (condition2 or condition3),condition1就会在外层条件中,因为之前提取
		List<Condition> outSideCondition = new ArrayList<Condition>();
//		stashOutSideConditions();
		outSideCondition.addAll(conditions);
		this.conditions.clear();
		for(SQLExpr sqlExpr : whereUnit.getSplitedExprList()) {
			sqlExpr.accept(this);
//            List<Condition> conditions = new ArrayList<Condition>();
//            conditions.addAll(getConditions()); conditions.addAll(outSideCondition);
          /**
           * 合并两个条件列表的元素为一个条件列表,减少不必要多的条件项</br>
           * 
           * @author SvenAugustus
           */
          List<Condition> conditions = mergeSqlConditionList(getConditions(), outSideCondition);
			retList.add(conditions);
			this.conditions.clear();
		}
		whereUnit.setConditionList(retList);
		
		for(WhereUnit subWhere : whereUnit.getSubWhereUnit()) {
			getConditionsFromWhereUnit(subWhere);
		}
	}
	
	/**
	 * 递归拆分OR
	 * 
	 * @param whereUnit
	 * TODO:考虑嵌套or语句,条件中有子查询、 exists等很多种复杂情况是否能兼容
	 */
	private void splitUntilNoOr(WhereUnit whereUnit) {
		if(whereUnit.isFinishedParse()) {
			if(whereUnit.getSubWhereUnit().size() > 0) {
				for(int i = 0; i < whereUnit.getSubWhereUnit().size(); i++) {
					splitUntilNoOr(whereUnit.getSubWhereUnit().get(i));
				}
			} 
		} else {
			SQLBinaryOpExpr expr = whereUnit.getCanSplitExpr();
			if(expr.getOperator() == SQLBinaryOperator.BooleanOr) {
//				whereUnit.addSplitedExpr(expr.getRight());
				addExprIfNotFalse(whereUnit, expr.getRight());
				if(expr.getLeft() instanceof SQLBinaryOpExpr) {
					whereUnit.setCanSplitExpr((SQLBinaryOpExpr)expr.getLeft());
					splitUntilNoOr(whereUnit);
				} else {
					addExprIfNotFalse(whereUnit, expr.getLeft());
				}
			} else {
				addExprIfNotFalse(whereUnit, expr);
				whereUnit.setFinishedParse(true);
			}
		}
    }

	private void addExprIfNotFalse(WhereUnit whereUnit, SQLExpr expr) {
		//非永假条件加入路由计算
		if(!RouterUtil.isConditionAlwaysFalse(expr)) {
			whereUnit.addSplitedExpr(expr);
		}
	}
	
	@Override
    public boolean visit(SQLAlterTableStatement x) {
        String tableName = x.getName().toString();
        TableStat stat = getTableStat(tableName,tableName);
        stat.incrementAlterCount();

        setCurrentTable(x, tableName);

        for (SQLAlterTableItem item : x.getItems()) {
            item.setParent(x);
            item.accept(this);
        }

        return false;
    }
    public boolean visit(MySqlCreateTableStatement x) {
        SQLName sqlName=  x.getName();
        if(sqlName!=null)
        {
            String table = sqlName.toString();
            if(table.startsWith("`"))
            {
                table=table.substring(1,table.length()-1);
            }
            setCurrentTable(table);
        }
        return false;
    }
    public boolean visit(MySqlInsertStatement x) {
        SQLName sqlName=  x.getTableName();
        if(sqlName!=null)
        {
            String table = sqlName.toString();
            if(table.startsWith("`"))
            {
                table=table.substring(1,table.length()-1);
            }
            setCurrentTable(sqlName.toString());
        }
        return false;
    }
	// DUAL
    public boolean visit(MySqlDeleteStatement x) {
        setAliasMap();

        setMode(x, Mode.Delete);

        accept(x.getFrom());
        accept(x.getUsing());
        x.getTableSource().accept(this);

        if (x.getTableSource() instanceof SQLExprTableSource) {
            SQLName tableName = (SQLName) ((SQLExprTableSource) x.getTableSource()).getExpr();
            String ident = tableName.toString();
            setCurrentTable(x, ident);

            TableStat stat = this.getTableStat(ident,ident);
            stat.incrementDeleteCount();
        }

        accept(x.getWhere());

        accept(x.getOrderBy());
        accept(x.getLimit());

        return false;
    }
    
    public void endVisit(MySqlDeleteStatement x) {
    }
    
    public boolean visit(SQLUpdateStatement x) {
        setAliasMap();

        setMode(x, Mode.Update);

        SQLName identName = x.getTableName();
        if (identName != null) {
            String ident = identName.toString();
            String alias = x.getTableSource().getAlias();
            setCurrentTable(ident);

            TableStat stat = getTableStat(ident);
            stat.incrementUpdateCount();

            Map<String, String> aliasMap = getAliasMap();
            
            aliasMap.put(ident, ident);
            if(alias != null) {
            	aliasMap.put(alias, ident);
            }
        } else {
            x.getTableSource().accept(this);
        }

        accept(x.getItems());
        accept(x.getWhere());

        return false;
    }
    
    @Override
    public void endVisit(MySqlHintStatement x) {
    	super.endVisit(x);
    }
    
    @Override
    public boolean visit(MySqlHintStatement x) {
    	List<SQLCommentHint> hits = x.getHints();
    	if(hits != null && !hits.isEmpty()) {
    		String schema = parseSchema(hits);
    		if(schema != null ) {
    			setCurrentTable(x, schema + ".");
    			return true;
    		}
    	}
    	return true;
    }
    
    private String parseSchema(List<SQLCommentHint> hits) {
    	String regx = "\\!mycat:schema\\s*=([\\s\\w]*)$";
    	for(SQLCommentHint hit : hits ) {
    		Pattern pattern = Pattern.compile(regx);
    		Matcher m = pattern.matcher(hit.getText());
    		if(m.matches()) {
    			return m.group(1).trim();
    		}
    	}
		return null;
    }

    public Queue<SQLSelect> getSubQuerys() {
		return subQuerys;
	}
	
	private void addSubQuerys(SQLSelect sqlselect){
		/* 多个 sqlselect 之间  , equals 和 hashcode 是相同的.去重时 都被过滤掉了. */
		if(subQuerys.isEmpty()){
			subQuerys.add(sqlselect);
			return;
		}
        boolean exists = false;
		Iterator<SQLSelect> iter = subQuerys.iterator();
		while(iter.hasNext()){
			SQLSelect ss = iter.next();
			if(ss.getQuery() instanceof SQLSelectQueryBlock
					&&sqlselect.getQuery() instanceof SQLSelectQueryBlock){
				SQLSelectQueryBlock current = (SQLSelectQueryBlock)sqlselect.getQuery();
				SQLSelectQueryBlock ssqb = (SQLSelectQueryBlock)ss.getQuery();
//                  if(!sqlSelectQueryBlockEquals(ssqb,current)){
//                    subQuerys.add(sqlselect);
//                  }
                /**
                 * 修正判定逻辑,应改为全不在subQuerys中才加入<br/>
                 * 
                 * @author SvenAugustus
                 */
                if(sqlSelectQueryBlockEquals(current,ssqb)){
                   exists = true;
                   break;
                }
				}
			}
        if(!exists) {
          subQuerys.add(sqlselect);
		}
	}
	
	/* 多个 sqlselect 之间  , equals 和 hashcode 是相同的.去重时 使用 SQLSelectQueryBlock equals 方法 */
    private boolean sqlSelectQueryBlockEquals(SQLSelectQueryBlock obj1,SQLSelectQueryBlock obj2) {
        if (obj1 == obj2) return true;
        if (obj2 == null) return false;
        if (obj1.getClass() != obj2.getClass()) return false;
        if (obj1.isParenthesized() ^ obj2.isParenthesized()) return false;
        if (obj1.getDistionOption() != obj2.getDistionOption()) return false;
        if (obj1.getFrom() == null) {
            if (obj2.getFrom() != null) return false;
        } else if (!obj1.getFrom().equals(obj2.getFrom())) return false;
        if (obj1.getGroupBy() == null) {
            if (obj2.getGroupBy() != null) return false;
        } else if (!obj1.getGroupBy().equals(obj2.getGroupBy())) return false;
        if (obj1.getInto() == null) {
            if (obj2.getInto() != null) return false;
        } else if (!obj1.getInto().equals(obj2.getInto())) return false;
        if (obj1.getSelectList() == null) {
            if (obj2.getSelectList() != null) return false;
        } else if (!obj1.getSelectList().equals(obj2.getSelectList())) return false;
        if (obj1.getWhere() == null) {
            if (obj2.getWhere() != null) return false;
        } else if (!obj1.getWhere().equals(obj2.getWhere())) return false;
        return true;
    }

	public boolean isHasChange() {
		return hasChange;
	}

	public boolean isSubqueryRelationOr() {
		return subqueryRelationOr;
	}
    
    /**
     * 判定当前的条件列表 是否 另外一个条件列表的 子集
     * 
     * @author SvenAugustus
     * @param current 当前的条件列表 
     * @param other 另外一个条件列表
     * @return
     */
    private boolean sqlConditionListInOther(List<Condition> current, List<Condition> other) {
      if (current == null) {
        if (other != null) {
          return false;
        }
        return true;
      }
      if (current.size() > other.size()) {
        return false;
      }
      if (other.size() == current.size()) {
        // 判定两个条件列表的元素是否内容相等
        return sqlConditionListEquals(current, other);
      }
      for (int j = 0; j < current.size(); j++) {
        boolean exists = false;
        for (int i = 0; i < other.size(); i++) {
          // 判定两个条件是否相等
          if (sqlConditionEquals(current.get(j), other.get(i))) {
            exists = true;
            break;
          }
        }
        if (!exists) {
          return false;
        }
      }
      return true;
    }
    
    /**
     * 判定两个条件列表的元素是否内容相等
     * 
     * @author SvenAugustus
     * @param list1
     * @param list2
     * @return
     */
    private boolean sqlConditionListEquals(List<Condition> list1, List<Condition> list2) {
      if (list1 == null) {
        if (list2 != null) {
          return false;
        }
        return true;
      }
      if (list2.size() != list1.size()) {
        return false;
      }
      int len = list1.size();
      for (int j = 0; j < len; j++) {
        boolean exists = false;
        for (int i = 0; i < len; i++) {
          // 判定两个条件是否相等
          if (sqlConditionEquals(list2.get(j), list1.get(i))) {
            exists = true;
            break;
          }
        }
        if (!exists) {
          return false;
        }
      }
      return true;
    }

    /**
     * 合并两个条件列表的元素为一个条件列表
     * 
     * @author SvenAugustus
     * @param list1 条件列表1
     * @param list2 条件列表2
     * @return
     */
    private List<Condition> mergeSqlConditionList(List<Condition> list1, List<Condition> list2) {
      if (list1 == null) {
        list1 = new ArrayList();
      }
      if (list2 == null) {
        list2 = new ArrayList();
      }
      List<Condition> retList = new ArrayList<Condition>();
      if (!list1.isEmpty() && !(list1.get(0) instanceof Condition)) {
        return retList;
      }
      if (!list2.isEmpty() && !(list2.get(0) instanceof Condition)) {
        return retList;
      }
      retList.addAll(list1);
      for (int j = 0; j < list2.size(); j++) {
        boolean exists = false;
        for (int i = 0; i < list1.size(); i++) {
          if (sqlConditionEquals(list2.get(j), list1.get(i))) {
            exists = true;
            break;
          }
        }
        if (!exists) {
          retList.add(list2.get(j));
        }
      }
      return retList;
    }
    
    /**
     * 判定两个条件是否相等
     * 
     * @author SvenAugustus
     * @param obj1
     * @param obj2
     * @return
     */
    private boolean sqlConditionEquals(Condition obj1, Condition obj2) {
      if (obj1 == obj2) {
        return true;
      }
      if (obj2 == null) {
        return false;
      }
      if (obj1.getClass() != obj2.getClass()) {
        return false;
      }
      Condition other = (Condition) obj2;
      if (obj1.getColumn() == null) {
        if (other.getColumn() != null) {
          return false;
        }
      } else if (!obj1.getColumn().equals(other.getColumn())) {
        return false;
      }
      if (obj1.getOperator() == null) {
        if (other.getOperator() != null) {
          return false;
        }
      } else if (!obj1.getOperator().equals(other.getOperator())) {
        return false;
      }
      if (obj1.getValues() == null) {
        if (other.getValues() != null) {
          return false;
        }
      } else {
        boolean notEquals=false;
        for (Object val1: obj1.getValues()) {
          for (Object val2: obj2.getValues()) {
            if(val1==null) {
              if(val2!=null) {
                notEquals=true;
                break;
              }
            }else if(!val1.equals(val2)) {
              notEquals=true;
              break;
            }
          }
          if(notEquals)break;
        }
        if(notEquals)
        return false;
      }
      return true;
    }
}