Package org.yaac.server.egql

Source Code of org.yaac.server.egql.SelectStatement

package org.yaac.server.egql;

import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newHashSet;

import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.yaac.server.egql.evaluator.AggregationEvaluator;
import org.yaac.server.egql.evaluator.Evaluator;
import org.yaac.server.egql.exception.EGQLE001Exception;
import org.yaac.server.egql.exception.EGQLE002Exception;
import org.yaac.server.egql.exception.EGQLException;
import org.yaac.server.egql.processor.ChannelMsgSender;
import org.yaac.server.egql.processor.DatastoreLoader;
import org.yaac.server.egql.processor.ProcessData.ProcessDataRecord;
import org.yaac.server.egql.processor.Processor;
import org.yaac.server.egql.processor.SelectProccesor;
import org.yaac.shared.egql.EGQLConstant;

import com.google.common.collect.ImmutableSet;

/**
* @author Max Zhu (thebbsky@gmail.com)
*
*/
public class SelectStatement extends Statement {

  /**
   *
   */
  private static final long serialVersionUID = 1L;
 
  private SelectClause selectClause;
 
  private FromClause fromClause;

  private WhereClause whereClause;
 
  private GroupByClause groupByClause;
 
  private HavingClause havingClause;
 
  public SelectClause getSelectClause() {
    return selectClause;
  }

  public void setSelectClause(SelectClause selectClause) {
    this.selectClause = selectClause;
  }

  public FromClause getFromClause() {
    return fromClause;
  }

  public void setFromClause(FromClause fromClause) {
    this.fromClause = fromClause;
  }
 
  public WhereClause getWhereClause() {
    return whereClause;
  }

  public void setWhereClause(WhereClause whereClause) {
    this.whereClause = whereClause;
  }

  public GroupByClause getGroupByClause() {
    return groupByClause;
  }

  public void setGroupByClause(GroupByClause groupByClause) {
    this.groupByClause = groupByClause;
  }

  public HavingClause getHavingClause() {
    return havingClause;
  }

  public void setHavingClause(HavingClause havingClause) {
    this.havingClause = havingClause;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((fromClause == null) ? 0 : fromClause.hashCode());
    result = prime * result + ((groupByClause == null) ? 0 : groupByClause.hashCode());
    result = prime * result + ((havingClause == null) ? 0 : havingClause.hashCode());
    result = prime * result + ((selectClause == null) ? 0 : selectClause.hashCode());
    result = prime * result + ((whereClause == null) ? 0 : whereClause.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    SelectStatement other = (SelectStatement) obj;
    if (fromClause == null) {
      if (other.fromClause != null)
        return false;
    } else if (!fromClause.equals(other.fromClause))
      return false;
    if (groupByClause == null) {
      if (other.groupByClause != null)
        return false;
    } else if (!groupByClause.equals(other.groupByClause))
      return false;
    if (havingClause == null) {
      if (other.havingClause != null)
        return false;
    } else if (!havingClause.equals(other.havingClause))
      return false;
    if (selectClause == null) {
      if (other.selectClause != null)
        return false;
    } else if (!selectClause.equals(other.selectClause))
      return false;
    if (whereClause == null) {
      if (other.whereClause != null)
        return false;
    } else if (!whereClause.equals(other.whereClause))
      return false;
    return true;
  }

  @Override
  public String toString() {
    return "SelectStatement [selectClause=" + selectClause + ", fromClause=" + fromClause + ", whereClause="
        + whereClause + ", groupByClause=" + groupByClause + ", havingClause=" + havingClause + "]";
  }
 
  /**
   * @return
   */
  public boolean isGroupByQuery() {
    return getGroupByClause() != null;
  }
 
  /**
   * @return true if there are aggregation functions AND no other non-aggregated field evaluators
   *
   * note that aggregation function doesn't has to be on top level
   * also, non aggregation functions can be expressions without fields like : 1 + 3
   */
  public boolean aggregationEvaluatorOnly() {
    boolean allAgg = true;
    for (Evaluator evaluator : getSelectClause().getItems()) {
      if (!evaluator.nonAggregationProperties().isEmpty()) {
        allAgg = false;
        break
      }
    }
   
    return allAgg && !isGroupByQuery();
  }

  /**
   * @return all aggregators in select caluse or having clause
   */
  public Collection<AggregationEvaluator> getAllAggregationEvaluators() {
    Set<AggregationEvaluator> result = newHashSet();
   
    for (Evaluator e : selectClause.getItems()) {
      result.addAll(e.aggregationChildren());
    }
   
    if (havingClause != null) {
      result.addAll(havingClause.getConditions().aggregationChildren());
    }

    return result;
  }

  @Override
  public void validate() throws EGQLException {   
    // validate all evaluators in select / where having clause
    for (Evaluator e : selectClause.getItems()) {
      e.validate();
    }
   
    if (whereClause != null) {
      whereClause.getConditions().validate();
    }
   
    if (havingClause != null) {
      havingClause.getConditions().validate();
    }

    Set<AggregationEvaluator> aggregationEvaluators =
      ImmutableSet.<AggregationEvaluator>builder().addAll(this.getAllAggregationEvaluators()).build();
   
    if (!aggregationEvaluators.isEmpty()) {
      // E001 : not a single-group group function
      {
        // all properties appear in select items MUST be in group by clause as well
        Set<EntityProperty> nonAggregationProperties = newHashSet();
        for (Evaluator e : selectClause.getItems()) {
           nonAggregationProperties.addAll(e.nonAggregationProperties());
        }
       
        if (!nonAggregationProperties.isEmpty()) {
          if (groupByClause == null) {
            throw new EGQLE001Exception();
          } else {
            nonAggregationProperties.removeAll(groupByClause.items());
            if (! nonAggregationProperties.isEmpty()) {
              // some fields are not in group by function
              throw new EGQLE001Exception()
            }
          }
        } 
      }
    }
   
    // E002 : havingClause : not a GROUP BY expression
    {
      if (havingClause != null) {  // having clause is optional
        // all properties appear in having items MUST be in group by clause as well
        Set<EntityProperty> s = havingClause.getConditions().nonAggregationProperties();
       
        if (groupByClause != null) {
          // it is possible to have a having clause without group by
          // eg, select count(home_team) from match having count(home_team) < 10
          s.removeAll(groupByClause.items())
        }
       
        if (! s.isEmpty()) {
          throw new EGQLE002Exception()
       
      }
    }
  }

  /**
   * isRejected if data in evaluation context does not match where clause
   *
   * @param record
   * @return
   */
  public boolean rejectedByWhereClause(ProcessDataRecord record) {
    return getWhereClause() != null && !whereClause.evaluate(record);
  }

  public boolean rejectedByHavingClause(ProcessDataRecord record) {
    return havingClause != null && !havingClause.evaluate(record);
  }

  @Override
  public List<Processor> generateProcessors() {
    Processor msgSender = new ChannelMsgSender(EGQLConstant.DEFAULT_MAX_RESULT);
    return newArrayList(datastoreLoader(), selector(), msgSender);
  }

  Processor datastoreLoader() {
    return new DatastoreLoader(
        this.getFromClause().getFromEntities().get(0).getEntityName(), EGQLConstant.DEFAULT_BATCH_SIZE);
  }
 
  Processor selector() {
    return new SelectProccesor(this);
  }
 
  @Override
  public boolean isSimpleStatement() {
    // at the moment always return false, return true if it's a very simple select statement like GQL??
    return false;
  }
}
TOP

Related Classes of org.yaac.server.egql.SelectStatement

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.