com.arcadedb.query.sql.parser.UpdateItem 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. OUpdateItem.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.Document;
import com.arcadedb.database.Identifiable;
import com.arcadedb.exception.CommandExecutionException;
import com.arcadedb.query.sql.executor.CommandContext;
import com.arcadedb.query.sql.executor.Result;
import com.arcadedb.query.sql.executor.ResultInternal;
import com.arcadedb.schema.DocumentType;
import com.arcadedb.schema.Property;
import com.arcadedb.schema.Type;
import java.util.*;
import java.util.stream.*;
public class UpdateItem extends SimpleNode {
public static final int OPERATOR_EQ = 0;
public static final int OPERATOR_PLUSASSIGN = 1;
public static final int OPERATOR_MINUSASSIGN = 2;
public static final int OPERATOR_STARASSIGN = 3;
public static final int OPERATOR_SLASHASSIGN = 4;
protected Identifier left;
protected Modifier leftModifier;
protected int operator;
protected Expression right;
public UpdateItem(final int id) {
super(id);
}
public void toString(final Map params, final StringBuilder builder) {
left.toString(params, builder);
if (leftModifier != null) {
leftModifier.toString(params, builder);
}
switch (operator) {
case OPERATOR_EQ:
builder.append(" = ");
break;
case OPERATOR_PLUSASSIGN:
builder.append(" += ");
break;
case OPERATOR_MINUSASSIGN:
builder.append(" -= ");
break;
case OPERATOR_STARASSIGN:
builder.append(" *= ");
break;
case OPERATOR_SLASHASSIGN:
builder.append(" /= ");
break;
default:
throw new IllegalArgumentException("Operator '" + operator + "' not supported in update");
}
right.toString(params, builder);
}
public UpdateItem copy() {
final UpdateItem result = new UpdateItem(-1);
result.left = left == null ? null : left.copy();
result.leftModifier = leftModifier == null ? null : leftModifier.copy();
result.operator = operator;
result.right = right == null ? null : right.copy();
return result;
}
@Override
public boolean equals(final Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
final UpdateItem that = (UpdateItem) o;
if (operator != that.operator)
return false;
if (!Objects.equals(left, that.left))
return false;
if (!Objects.equals(leftModifier, that.leftModifier))
return false;
return Objects.equals(right, that.right);
}
@Override
public int hashCode() {
int result = left != null ? left.hashCode() : 0;
result = 31 * result + (leftModifier != null ? leftModifier.hashCode() : 0);
result = 31 * result + operator;
result = 31 * result + (right != null ? right.hashCode() : 0);
return result;
}
public void applyUpdate(final ResultInternal doc, final CommandContext context) {
final Object rightValue = right.execute(doc, context);
if (leftModifier == null) {
applyOperation(doc, left, rightValue, context);
} else {
final Object val = doc.getProperty(left.getStringValue());
leftModifier.setValue(doc, val, rightValue, context);
}
}
public void applyOperation(final ResultInternal doc, final Identifier attrName, final Object rightValue, final CommandContext context) {
switch (operator) {
case OPERATOR_EQ:
Object newValue = extractFromResult(rightValue);
newValue = convertToPropertyType(doc, attrName, newValue);
doc.setProperty(attrName.getStringValue(), newValue);
break;
case OPERATOR_MINUSASSIGN:
doc.setProperty(attrName.getStringValue(), calculateNewValue(doc, context, MathExpression.Operator.MINUS));
break;
case OPERATOR_PLUSASSIGN:
doc.setProperty(attrName.getStringValue(), calculateNewValue(doc, context, MathExpression.Operator.PLUS));
break;
case OPERATOR_SLASHASSIGN:
doc.setProperty(attrName.getStringValue(), calculateNewValue(doc, context, MathExpression.Operator.SLASH));
break;
case OPERATOR_STARASSIGN:
doc.setProperty(attrName.getStringValue(), calculateNewValue(doc, context, MathExpression.Operator.STAR));
break;
}
}
private Object convertToPropertyType(final ResultInternal res, final Identifier attrName, Object newValue) {
final Document doc = res.toElement();
final Optional optSchema = Optional.ofNullable(doc.getType());
if (optSchema.isEmpty()) {
return newValue;
}
if (!optSchema.get().existsProperty(attrName.getStringValue()))
return newValue;
final Property prop = optSchema.get().getPolymorphicPropertyIfExists(attrName.getStringValue());
if (prop == null) {
return newValue;
}
if (newValue instanceof Collection) {
if (prop.getType() == Type.LINK) {
if (((Collection) newValue).isEmpty()) {
newValue = null;
} else if (((Collection) newValue).size() == 1) {
newValue = ((Collection) newValue).iterator().next();
} else {
throw new CommandExecutionException("Cannot assign a collection to a LINK property");
}
}
}
return newValue;
}
private Object extractFromResult(final Object value) {
if (value instanceof Result) {
if (((Result) value).isElement())
return ((Result) value).toElement();
else if (((Result) value).getPropertyNames().size() == 1)
return ((Result) value).getProperty(((Result) value).getPropertyNames().iterator().next());
else
return ((Result) value).toMap();
} else if (value instanceof Identifiable)
return value;
else if (value instanceof List && containsOResult((Collection) value))
return ((List) value).stream().map(x -> extractFromResult(x)).collect(Collectors.toList());
else if (value instanceof Set && containsOResult((Collection) value))
return ((Set) value).stream().map(x -> extractFromResult(x)).collect(Collectors.toSet());
return value;
}
private boolean containsOResult(final Collection value) {
return value.stream().anyMatch(x -> x instanceof Result);
}
private Object calculateNewValue(final ResultInternal doc, final CommandContext context, final MathExpression.Operator explicitOperator) {
final Expression leftEx = new Expression(left.copy());
if (leftModifier != null)
((BaseExpression) leftEx.mathExpression).modifier = leftModifier.copy();
final MathExpression mathExp = new MathExpression(-1);
mathExp.getChildExpressions().add(leftEx.getMathExpression());
mathExp.getChildExpressions().add(new ParenthesisExpression(right.copy()));
mathExp.getOperators().add(explicitOperator);
return mathExp.execute(doc, context);
}
public Identifier getLeft() {
return left;
}
public void setLeft(final Identifier left) {
this.left = left;
}
public Modifier getLeftModifier() {
return leftModifier;
}
public void setLeftModifier(final Modifier leftModifier) {
this.leftModifier = leftModifier;
}
public int getOperator() {
return operator;
}
public void setOperator(final int operator) {
this.operator = operator;
}
public Expression getRight() {
return right;
}
public void setRight(final Expression right) {
this.right = right;
}
}
/* JavaCC - OriginalChecksum=df7444be87bba741316df8df0d653600 (do not edit this line) */
© 2015 - 2024 Weber Informatics LLC | Privacy Policy