All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.arcadedb.query.sql.parser.SelectStatement Maven / Gradle / Ivy

There is a newer version: 24.11.1
Show newest version
/*
 * Copyright © 2021-present Arcade Data Ltd ([email protected])
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-FileCopyrightText: 2021-present Arcade Data Ltd ([email protected])
 * SPDX-License-Identifier: Apache-2.0
 */
/* 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_USERTYPE_VISIBILITY_PUBLIC=true */
/*


 */
package com.arcadedb.query.sql.parser;

import com.arcadedb.database.Database;
import com.arcadedb.database.DatabaseInternal;
import com.arcadedb.exception.ArcadeDBException;
import com.arcadedb.exception.CommandSQLParsingException;
import com.arcadedb.query.sql.executor.BasicCommandContext;
import com.arcadedb.query.sql.executor.CommandContext;
import com.arcadedb.query.sql.executor.InternalExecutionPlan;
import com.arcadedb.query.sql.executor.ResultSet;
import com.arcadedb.query.sql.executor.SelectExecutionPlanner;

import java.util.*;

import static com.arcadedb.query.sql.parser.SqlParserTreeConstants.JJTLIMIT;
import static com.arcadedb.query.sql.parser.SqlParserTreeConstants.JJTTIMEOUT;

public class SelectStatement extends Statement {
  protected FromClause  target;
  protected Projection  projection;
  protected WhereClause whereClause;
  protected GroupBy     groupBy;
  protected OrderBy     orderBy;
  protected Unwind      unwind;
  protected Skip        skip;
  protected LetClause   letClause;

  public SelectStatement(final int id) {
    super(id);
  }

  public Projection getProjection() {
    return projection;
  }

  public FromClause getTarget() {
    return target;
  }

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

  public WhereClause getWhereClause() {
    return whereClause;
  }

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

  public GroupBy getGroupBy() {
    return groupBy;
  }

  public OrderBy getOrderBy() {
    return orderBy;
  }

  public Skip getSkip() {
    return skip;
  }

  public LetClause getLetClause() {
    return letClause;
  }

  public void toString(final Map params, final 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 (timeout != null) {
      timeout.toString(params, builder);
    }
  }

  public void validate() throws CommandSQLParsingException {
    if (projection != null) {
      projection.validate();
      if (projection.isExpand() && groupBy != null) {
        throw new CommandSQLParsingException("expand() cannot be used together with GROUP BY");
      }
    }
  }

  @Override
  public boolean executionPlanCanBeCached() {
    if (originalStatementAsString == null && originalStatement == null)
      return false;

    if (this.target != null && !this.target.isCacheable())
      return false;

    if (this.letClause != null && !this.letClause.isCacheable())
      return false;

    if (projection != null && !this.projection.isCacheable())
      return false;

    return whereClause == null || whereClause.isCacheable();
  }

  @Override
  public ResultSet execute(final Database db, final Object[] args, final CommandContext parentContext, final boolean usePlanCache) {
    final BasicCommandContext context = new BasicCommandContext();
    if (parentContext != null) {
      context.setParentWithoutOverridingChild(parentContext);
    }
    context.setDatabase(db);
    final Map params = new HashMap<>();
    if (args != null) {
      if (args.length == 1 && args[0] instanceof Map)
        params.putAll((Map) args[0]);
      else
        for (int i = 0; i < args.length; i++)
          params.put(String.valueOf(i), args[i]);
    }

    setProfilingConstraints((DatabaseInternal) db);

    context.setInputParameters(params);
    final InternalExecutionPlan executionPlan = createExecutionPlan(context, false);
    final LocalResultSet result = new LocalResultSet(executionPlan);
    return result;
  }

  @Override
  public ResultSet execute(final Database db, final Map params, final CommandContext parentContext,
      final boolean usePlanCache) {
    final BasicCommandContext context = new BasicCommandContext();
    if (parentContext != null)
      context.setParentWithoutOverridingChild(parentContext);

    context.setDatabase(db);

    setProfilingConstraints((DatabaseInternal) db);

    boolean profileExecution = false;
    if (params != null && params.containsKey("$profileExecution")) {
      profileExecution = (Boolean) params.remove("$profileExecution");
    }

    context.setInputParameters(params);
    final InternalExecutionPlan executionPlan = createExecutionPlan(context, profileExecution);
    return new LocalResultSet(executionPlan);
  }

  public InternalExecutionPlan createExecutionPlan(final CommandContext context, final boolean enableProfiling) {
    final SelectExecutionPlanner planner = new SelectExecutionPlanner(this);
    return planner.createExecutionPlan(context, enableProfiling);
  }

  @Override
  public SelectStatement copy() {
    try {
      final SelectStatement result = getClass().getConstructor(Integer.TYPE).newInstance(-1);
      result.originalStatement = originalStatement;
      result.target = target == null ? null : target.copy();
      result.projection = projection == null ? null : projection.copy();
      result.whereClause = whereClause == null ? null : whereClause.copy();
      result.groupBy = groupBy == null ? null : groupBy.copy();
      result.orderBy = orderBy == null ? null : orderBy.copy();
      result.unwind = unwind == null ? null : unwind.copy();
      result.skip = skip == null ? null : skip.copy();
      result.limit = limit == null ? null : limit.copy();
      result.letClause = letClause == null ? null : letClause.copy();
      result.timeout = timeout == null ? null : timeout.copy();
      return result;
    } catch (final Exception e) {
      throw new ArcadeDBException(e);
    }
  }

  @Override
  protected Object[] getIdentityElements() {
    return new Object[] { target, projection, whereClause, groupBy, orderBy, unwind, skip, limit, letClause, timeout };
  }

  @Override
  public boolean refersToParent() {
    //no FROM, if a sub-query refers to parent it does not make sense, so that reference will be just ignored
    if (projection != null && projection.refersToParent())
      return true;

    if (target != null && target.refersToParent())
      return true;

    if (whereClause != null && whereClause.refersToParent())
      return true;

    if (groupBy != null && groupBy.refersToParent())
      return true;

    if (orderBy != null && orderBy.refersToParent())
      return true;

    return letClause != null && letClause.refersToParent();
  }

  public Unwind getUnwind() {
    return unwind;
  }

  @Override
  public boolean isIdempotent() {
    return true;
  }

  public void setUnwind(final Unwind unwind) {
    this.unwind = unwind;
  }

  private void setProfilingConstraints(final DatabaseInternal db) {
    final long profiledLimit = db.getResultSetLimit();
    if (profiledLimit > -1 && (limit == null || limit.num.value.longValue() > profiledLimit))
      setLimit(new Limit(JJTLIMIT).setValue((int) profiledLimit));

    final long profiledTimeout = db.getReadTimeout();
    if (profiledTimeout > -1 && (timeout == null || timeout.val.longValue() > profiledTimeout))
      setTimeout(new Timeout(JJTTIMEOUT).setValue((int) profiledTimeout));
  }
}
/* JavaCC - OriginalChecksum=b26959b9726a8cf35d6283eca931da6b (do not edit this line) */




© 2015 - 2024 Weber Informatics LLC | Privacy Policy