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

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

/*
 * 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. OExpression.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.Identifiable;
import com.arcadedb.database.Record;
import com.arcadedb.exception.CommandExecutionException;
import com.arcadedb.query.sql.executor.AggregationContext;
import com.arcadedb.query.sql.executor.CommandContext;
import com.arcadedb.query.sql.executor.Result;
import com.arcadedb.query.sql.executor.ResultInternal;

import java.util.*;

public class Expression extends SimpleNode {
  protected boolean               singleQuotes;
  protected boolean               doubleQuotes;
  protected boolean               isNull = false;
  protected Rid                   rid;
  protected MathExpression        mathExpression;
  protected ArrayConcatExpression arrayConcatExpression;
  protected Json                  json;
  protected Boolean               booleanValue;
  protected WhereClause           whereCondition;

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

  public Expression(final Identifier identifier) {
    mathExpression = new BaseExpression(identifier);
  }

  public Expression(final Identifier identifier, final Modifier modifier) {
    mathExpression = new BaseExpression(identifier, modifier);
  }

  public Expression(final RecordAttribute attr, final Modifier modifier) {
    mathExpression = new BaseExpression(attr, modifier);
  }

  public Object execute(final Identifiable iCurrentRecord, final CommandContext context) {
    if (isNull)
      return null;
    else if (rid != null)
      return rid.toRecordId(iCurrentRecord, context);
    else if (mathExpression != null)
      return mathExpression.execute(iCurrentRecord, context);
    else if (whereCondition != null)
      return whereCondition.matchesFilters(iCurrentRecord, context);
    else if (arrayConcatExpression != null)
      return arrayConcatExpression.execute(iCurrentRecord, context);
    else if (json != null)
      return json.toMap(iCurrentRecord, context);
    else if (booleanValue != null)
      return booleanValue;
    else if (value instanceof PNumber)
      return ((PNumber) value).getValue();//only for old executor (manually replaced params)

    return value;
  }

  public Object execute(final Result iCurrentRecord, final CommandContext context) {
    if (isNull)
      return null;
    else if (rid != null)
      return rid.toRecordId(iCurrentRecord, context);
    else if (mathExpression != null)
      return mathExpression.execute(iCurrentRecord, context);
    else if (whereCondition != null)
      return whereCondition.matchesFilters(iCurrentRecord, context);
    else if (arrayConcatExpression != null)
      return arrayConcatExpression.execute(iCurrentRecord, context);
    else if (json != null)
      return json.toMap(iCurrentRecord, context);
    else if (booleanValue != null)
      return booleanValue;
    else if (value instanceof PNumber)
      return ((PNumber) value).getValue();//only for old executor (manually replaced params)

    return value;
  }

  public boolean isBaseIdentifier() {
    if (mathExpression != null) {
      return mathExpression.isBaseIdentifier();
    }
    if (value instanceof MathExpression) {//only backward stuff, remote it
      return ((MathExpression) value).isBaseIdentifier();
    }

    return false;
  }

  public boolean isEarlyCalculated(final CommandContext context) {
    if (this.mathExpression != null)
      return this.mathExpression.isEarlyCalculated(context);
    else if (this.whereCondition != null)
      return false;
    else if (this.arrayConcatExpression != null)
      return this.arrayConcatExpression.isEarlyCalculated(context);
    else if (booleanValue != null)
      return true;
    else if (value instanceof Number)
      return true;
    else if (value instanceof String)
      return true;
    else if (value instanceof MathExpression)
      return ((MathExpression) value).isEarlyCalculated(context);

    return false;
  }

  public Identifier getDefaultAlias() {
    final Identifier identifier;
    if (isBaseIdentifier()) {
      identifier = new Identifier(((BaseExpression) mathExpression).identifier.getSuffix().identifier.getStringValue());
    } else {
      identifier = new Identifier(this.toString());
    }
    return identifier;
  }

  public void toString(final Map params, final StringBuilder builder) {
    //    if (value == null) {
    //      builder.append("null");
    //    } else if (value instanceof SimpleNode) {
    //      ((SimpleNode) value).toString(params, builder);
    //    } else if (value instanceof String) {
    //      if (Boolean.TRUE.equals(singleQuotes)) {
    //        builder.append("'" + value + "'");
    //      } else {
    //        builder.append("\"" + value + "\"");
    //      }
    //    } else {
    //      builder.append("" + value);
    //    }

    if (isNull)
      builder.append("null");
    else if (rid != null)
      rid.toString(params, builder);
    else if (mathExpression != null)
      mathExpression.toString(params, builder);
    else if (whereCondition != null)
      whereCondition.toString(params, builder);
    else if (arrayConcatExpression != null)
      arrayConcatExpression.toString(params, builder);
    else if (json != null)
      json.toString(params, builder);
    else if (booleanValue != null)
      builder.append(booleanValue);
    else if (value instanceof SimpleNode)
      ((SimpleNode) value).toString(params, builder);//only for translated input params, will disappear with new executor
    else if (value instanceof String) {
      if (singleQuotes) {
        builder.append("'" + value + "'");
      } else {
        builder.append("\"" + value + "\"");
      }

    } else {
      builder.append("" + value);//only for translated input params, will disappear with new executor
    }
  }

  public static String encode(final String s) {
    final StringBuilder builder = new StringBuilder(s.length());
    for (final char c : s.toCharArray()) {
      if (c == '\n') {
        builder.append("\\n");
        continue;
      }
      if (c == '\t') {
        builder.append("\\t");
        continue;
      }
      if (c == '\\' || c == '"') {
        builder.append("\\");
      }
      builder.append(c);
    }
    return builder.toString();
  }

  public boolean isIndexedFunctionCal(final CommandContext context) {
    if (mathExpression != null)
      return mathExpression.isIndexedFunctionCall(context);

    return false;
  }

  public static String encodeSingle(final String s) {
    final StringBuilder builder = new StringBuilder(s.length());
    for (final char c : s.toCharArray()) {
      if (c == '\n') {
        builder.append("\\n");
        continue;
      }
      if (c == '\t') {
        builder.append("\\t");
        continue;
      }
      if (c == '\\' || c == '\'') {
        builder.append("\\");
      }
      builder.append(c);
    }
    return builder.toString();
  }

  public long estimateIndexedFunction(final FromClause target, final CommandContext context, final BinaryCompareOperator operator, final Object right) {
    if (mathExpression != null) {
      return mathExpression.estimateIndexedFunction(target, context, operator, right);
    }
    return -1;
  }

  public Iterable executeIndexedFunction(final FromClause target, final CommandContext context, final BinaryCompareOperator operator,
      final Object right) {
    if (mathExpression != null) {
      return mathExpression.executeIndexedFunction(target, context, operator, right);
    }
    return null;
  }

  /**
   * tests if current expression is an indexed function AND that function can also be executed without using the index
   *
   * @param target   the query target
   * @param context  the execution context
   * @param operator
   * @param right
   *
   * @return true if current expression is an indexed function AND that function can also be executed without using the index, false
   * otherwise
   */
  public boolean canExecuteIndexedFunctionWithoutIndex(final FromClause target, final CommandContext context, final BinaryCompareOperator operator,
      final Object right) {
    if (mathExpression != null) {
      return mathExpression.canExecuteIndexedFunctionWithoutIndex(target, context, operator, right);
    }
    return false;
  }

  /**
   * tests if current expression is an indexed function AND that function can be used on this target
   *
   * @param target   the query target
   * @param context  the execution context
   * @param operator
   * @param right
   *
   * @return true if current expression involves an indexed function AND that function can be used on this target, false otherwise
   */
  public boolean allowsIndexedFunctionExecutionOnTarget(final FromClause target, final CommandContext context, final BinaryCompareOperator operator,
      final Object right) {
    if (mathExpression != null) {
      return mathExpression.allowsIndexedFunctionExecutionOnTarget(target, context, operator, right);
    }
    return false;
  }

  /**
   * tests if current expression is an indexed function AND the function has also to be executed after the index search. In some
   * cases, the index search is accurate, so this condition can be excluded from further evaluation. In other cases the result from
   * the index is a superset of the expected result, so the function has to be executed anyway for further filtering
   *
   * @param target  the query target
   * @param context the execution context
   *
   * @return true if current expression involves an indexed function AND the function has also to be executed after the index
   * search.
   */
  public boolean executeIndexedFunctionAfterIndexSearch(final FromClause target, final CommandContext context, final BinaryCompareOperator operator,
      final Object right) {
    if (mathExpression != null) {
      return mathExpression.executeIndexedFunctionAfterIndexSearch(target, context, operator, right);
    }
    return false;
  }

  public boolean isExpand() {
    if (mathExpression != null) {
      return mathExpression.isExpand();
    }
    return false;
  }

  public Expression getExpandContent() {
    return mathExpression.getExpandContent();
  }

  public boolean isAggregate(final CommandContext context) {
    if (mathExpression != null && mathExpression.isAggregate(context)) {
      return true;
    }
    if (arrayConcatExpression != null && arrayConcatExpression.isAggregate(context)) {
      return true;
    }
    return json != null && json.isAggregate(context);
  }

  public Expression splitForAggregation(final AggregateProjectionSplit aggregateSplit, final CommandContext context) {
    if (isAggregate(context)) {
      final Expression result = new Expression(-1);
      if (mathExpression != null) {
        final SimpleNode splitResult = mathExpression.splitForAggregation(aggregateSplit, context);
        if (splitResult instanceof MathExpression) {
          result.mathExpression = (MathExpression) splitResult;
        } else if (splitResult instanceof Expression) {
          return (Expression) splitResult;
        } else {
          throw new IllegalStateException("something went wrong while splitting expression for aggregate " + this);
        }
      }
      if (arrayConcatExpression != null) {
        final SimpleNode splitResult = arrayConcatExpression.splitForAggregation(context);
        if (splitResult instanceof ArrayConcatExpression) {
          result.arrayConcatExpression = (ArrayConcatExpression) splitResult;
        } else if (splitResult instanceof Expression) {
          return (Expression) splitResult;
        } else {
          throw new IllegalStateException("something went wrong while splitting expression for aggregate " + this);
        }
      }
      if (json != null)
        result.json = json.splitForAggregation(aggregateSplit, context);

      return result;
    } else {
      return this;
    }
  }

  public AggregationContext getAggregationContext(final CommandContext context) {
    if (mathExpression != null) {
      return mathExpression.getAggregationContext(context);
    } else if (arrayConcatExpression != null) {
      return arrayConcatExpression.getAggregationContext(context);
    } else {
      throw new CommandExecutionException("Cannot aggregate on " + this);
    }
  }

  public Expression copy() {
    final Expression result = new Expression(-1);
    result.singleQuotes = singleQuotes;
    result.doubleQuotes = doubleQuotes;
    result.isNull = isNull;
    result.rid = rid == null ? null : rid.copy();
    result.mathExpression = mathExpression == null ? null : mathExpression.copy();
    result.whereCondition = whereCondition == null ? null : whereCondition.copy();
    result.arrayConcatExpression = arrayConcatExpression == null ? null : arrayConcatExpression.copy();
    result.json = json == null ? null : json.copy();
    result.booleanValue = booleanValue;
    return result;
  }

  public void setMathExpression(final MathExpression mathExpression) {
    this.mathExpression = mathExpression;
  }

  public void extractSubQueries(final SubQueryCollector collector) {
    if (mathExpression != null) {
      mathExpression.extractSubQueries(collector);
    }
    if (arrayConcatExpression != null) {
      arrayConcatExpression.extractSubQueries(collector);
    }
    if (json != null) {
      json.extractSubQueries(collector);
    }
  }

  public void extractSubQueries(final Identifier letAlias, final SubQueryCollector collector) {
    if (mathExpression != null) {
      mathExpression.extractSubQueries(letAlias, collector);
    }
    if (arrayConcatExpression != null) {
      arrayConcatExpression.extractSubQueries(collector);
    }
    if (json != null) {
      json.extractSubQueries(collector);
    }
  }

  public Rid getRid() {
    return rid;
  }

  public void setRid(final Rid rid) {
    this.rid = rid;
  }

  public MathExpression getMathExpression() {
    return mathExpression;
  }

  /**
   * if the condition involved the current pattern (MATCH statement, eg. $matched.something = foo), returns the name of involved
   * pattern aliases ("something" in this case)
   *
   * @return a list of pattern aliases involved in this condition. Null it does not involve the pattern
   */
  List getMatchPatternInvolvedAliases() {
    if (mathExpression != null)
      return mathExpression.getMatchPatternInvolvedAliases();
    if (arrayConcatExpression != null)
      return arrayConcatExpression.getMatchPatternInvolvedAliases();
    return null;
  }

  public void applyRemove(final ResultInternal result, final CommandContext context) {
    if (mathExpression != null) {
      mathExpression.applyRemove(result, context);
    } else {
      throw new CommandExecutionException("Cannot apply REMOVE " + this);
    }
  }

  public boolean isCount() {
    if (mathExpression == null) {
      return false;
    }
    return mathExpression.isCount();
  }

  public ArrayConcatExpression getArrayConcatExpression() {
    return arrayConcatExpression;
  }

  public void setArrayConcatExpression(final ArrayConcatExpression arrayConcatExpression) {
    this.arrayConcatExpression = arrayConcatExpression;
  }

  public boolean isDefinedFor(final Result currentRecord) {
    if (mathExpression != null) {
      return mathExpression.isDefinedFor(currentRecord);
    } else {
      return true;
    }
  }

  public boolean isDefinedFor(final Record currentRecord) {
    if (mathExpression != null) {
      return mathExpression.isDefinedFor(currentRecord);
    } else {
      return true;
    }
  }

  @Override
  protected Object[] getIdentityElements() {
    return new Object[] { isNull, singleQuotes, doubleQuotes, rid, mathExpression, arrayConcatExpression, json, booleanValue };
  }

  @Override
  protected SimpleNode[] getCacheableElements() {
    return new SimpleNode[] { mathExpression, arrayConcatExpression, json };
  }
}
/* JavaCC - OriginalChecksum=9c860224b121acdc89522ae97010be01 (do not edit this line) */




© 2015 - 2025 Weber Informatics LLC | Privacy Policy