/* Generated By:JJTree: Do not edit this line. OSelectStatement.java Version 4.3 */
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=true,NODE_PREFIX=O,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package com.orientechnologies.orient.core.sql.parser;

import com.orientechnologies.orient.core.command.OBasicCommandContext;
import com.orientechnologies.orient.core.command.OCommandContext;
import com.orientechnologies.orient.core.db.ODatabase;
import com.orientechnologies.orient.core.sql.OCommandSQLParsingException;
import com.orientechnologies.orient.core.sql.executor.OExecutionPlan;
import com.orientechnologies.orient.core.sql.executor.OSelectExecutionPlanner;
import com.orientechnologies.orient.core.sql.executor.OTodoResultSet;
import com.orientechnologies.orient.core.storage.OStorage;

import java.util.Map;

public class OSelectStatement extends OStatement {

  protected OFromClause target;

  protected OProjection projection;

  protected OWhereClause whereClause;

  protected OGroupBy groupBy;

  protected OOrderBy orderBy;

  protected OUnwind unwind;

  protected OSkip skip;

  protected OLimit limit;

  protected OStorage.LOCKING_STRATEGY lockRecord = null;

  protected OFetchPlan fetchPlan;

  protected OLetClause letClause;

  protected OTimeout timeout;

  protected Boolean parallel;

  protected Boolean noCache;

  public OSelectStatement(int id) {
    super(id);
  }

  public OSelectStatement(OrientSql p, int id) {
    super(p, id);
  }

  public OProjection getProjection() {
    return projection;
  }

  public void setProjection(OProjection projection) {
    this.projection = projection;
  }

  public OFromClause getTarget() {
    return target;
  }

  public void setTarget(OFromClause target) {
    this.target = target;
  }

  public OWhereClause getWhereClause() {
    return whereClause;
  }

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

  public OGroupBy getGroupBy() {
    return groupBy;
  }

  public void setGroupBy(OGroupBy groupBy) {
    this.groupBy = groupBy;
  }

  public OOrderBy getOrderBy() {
    return orderBy;
  }

  public void setOrderBy(OOrderBy orderBy) {
    this.orderBy = orderBy;
  }

  public OSkip getSkip() {
    return skip;
  }

  public void setSkip(OSkip skip) {
    this.skip = skip;
  }

  public OLimit getLimit() {
    return limit;
  }

  public void setLimit(OLimit limit) {
    this.limit = limit;
  }

  public OStorage.LOCKING_STRATEGY getLockRecord() {
    return lockRecord;
  }

  public void setLockRecord(OStorage.LOCKING_STRATEGY lockRecord) {
    this.lockRecord = lockRecord;
  }

  public OFetchPlan getFetchPlan() {
    return fetchPlan;
  }

  public void setFetchPlan(OFetchPlan fetchPlan) {
    this.fetchPlan = fetchPlan;
  }

  public OLetClause getLetClause() {
    return letClause;
  }

  public void setLetClause(OLetClause letClause) {
    this.letClause = letClause;
  }

  public void toString(Map<Object, Object> params, StringBuilder builder) {

    builder.append("SELECT");
    if (projection != null) {
      builder.append(" ");
      projection.toString(params, builder);
    }
    if (target != null) {
      builder.append(" FROM ");
      target.toString(params, builder);
    }

    if (letClause != null) {
      builder.append(" ");
      letClause.toString(params, builder);
    }

    if (whereClause != null) {
      builder.append(" WHERE ");
      whereClause.toString(params, builder);
    }

    if (groupBy != null) {
      builder.append(" ");
      groupBy.toString(params, builder);
    }

    if (orderBy != null) {
      builder.append(" ");
      orderBy.toString(params, builder);
    }

    if (unwind != null) {
      builder.append(" ");
      unwind.toString(params, builder);
    }

    if (skip != null) {
      skip.toString(params, builder);
    }

    if (limit != null) {
      limit.toString(params, builder);
    }

    if (lockRecord != null) {
      builder.append(" LOCK ");
      switch (lockRecord) {
      case DEFAULT:
        builder.append("DEFAULT");
        break;
      case EXCLUSIVE_LOCK:
        builder.append("RECORD");
        break;
      case SHARED_LOCK:
        builder.append("SHARED");
        break;
      case NONE:
        builder.append("NONE");
        break;
      }
    }

    if (fetchPlan != null) {
      builder.append(" ");
      fetchPlan.toString(params, builder);
    }

    if (timeout != null) {
      timeout.toString(params, builder);
    }

    if (Boolean.TRUE.equals(parallel)) {
      builder.append(" PARALLEL");
    }

    if (Boolean.TRUE.equals(noCache)) {
      builder.append(" NOCACHE");
    }
  }

  public void validate(OrientSql.ValidationStats stats) throws OCommandSQLParsingException {
    if (projection != null) {
      projection.validate();
    }
  }

  @Override public OTodoResultSet execute(ODatabase db, Object[] args) {
    OBasicCommandContext ctx = new OBasicCommandContext();
    ctx.setDatabase(db);
    ctx.setArgs(args);
    OExecutionPlan executionPlan = createExecutionPlan(ctx);

    return new OExternalResultSet(executionPlan);

  }

  public OExecutionPlan createExecutionPlan(OCommandContext ctx) {
    OSelectExecutionPlanner planner = new OSelectExecutionPlanner(this);
    return planner.createExecutionPlan(ctx);
  }


}
/* JavaCC - OriginalChecksum=b26959b9726a8cf35d6283eca931da6b (do not edit this line) */

@@ -4846,24 +4846,190 @@
 validate();%0A
+      %0A      if (projection.isExpand() && groupBy != null) %7B%0A        throw new OCommandSQLParsingException(%22expand() cannot be used together with GROUP BY%22);%0A      %7D%0A
     %7D%0A  %7D%0A%0A 
@@ -5515,17 +5515,16 @@
 );%0A  %7D%0A%0A
-%0A
 %7D%0A/* Jav

Enhance SELECT validation