package io.ebeaninternal.server.expression;

import io.ebean.event.BeanQueryRequest;
import io.ebeaninternal.api.ManyWhereJoins;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.SpiExpressionValidation;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.id.IdBinder;

import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;

In a collection of Id values.
/** * In a collection of Id values. */
public class IdInExpression extends NonPrepareExpression { private final Collection<?> idCollection; private boolean multiValueIdSupported; public IdInExpression(Collection<?> idCollection) { this.idCollection = idCollection; } @Override public void prepareExpression(BeanQueryRequest<?> request) { multiValueIdSupported = request.isMultiValueIdSupported(); } @Override public String nestedPath(BeanDescriptor<?> desc) { return null; } @Override public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) { } @Override public void writeDocQuery(DocQueryContext context) throws IOException { context.writeIds(idCollection); } @Override public void validate(SpiExpressionValidation validation) { // always valid } @Override public void addBindValues(SpiExpressionRequest request) { // Bind the Id values including EmbeddedId and multiple Id DefaultExpressionRequest r = (DefaultExpressionRequest) request; BeanDescriptor<?> descriptor = r.getBeanDescriptor(); IdBinder idBinder = descriptor.getIdBinder(); idBinder.addIdInBindValues(request, idCollection); }
For use with deleting non attached detail beans during stateless update.
/** * For use with deleting non attached detail beans during stateless update. */
public void addSqlNoAlias(SpiExpressionRequest request) { DefaultExpressionRequest r = (DefaultExpressionRequest) request; BeanDescriptor<?> descriptor = r.getBeanDescriptor(); IdBinder idBinder = descriptor.getIdBinder(); if (idCollection.isEmpty()) { request.append("1=0"); // append false for this stage } else { request.append(descriptor.getIdBinder().getBindIdInSql(null)); String inClause = idBinder.getIdInValueExpr(false, idCollection.size()); request.append(inClause); } } @Override public void addSql(SpiExpressionRequest request) { DefaultExpressionRequest r = (DefaultExpressionRequest) request; BeanDescriptor<?> descriptor = r.getBeanDescriptor(); IdBinder idBinder = descriptor.getIdBinder(); if (idCollection.isEmpty()) { request.append("1=0"); // append false for this stage } else { request.append(descriptor.getIdBinderInLHSSql()); String inClause = idBinder.getIdInValueExpr(false, idCollection.size()); request.append(inClause); } }
Incorporates the number of Id values to bind.
/** * Incorporates the number of Id values to bind. */
@Override public void queryPlanHash(StringBuilder builder) { builder.append("IdIn[?"); if (!multiValueIdSupported) { // query plan specific to the number of parameters in the IN clause builder.append(idCollection.size()); } builder.append("]"); } @Override public int queryBindHash() { return idCollection.hashCode(); } @Override public boolean isSameByBind(SpiExpression other) { IdInExpression that = (IdInExpression) other; if (this.idCollection.size() != that.idCollection.size()) { return false; } Iterator<?> it = that.idCollection.iterator(); for (Object id1 : idCollection) { Object id2 = it.next(); if (!id1.equals(id2)) { return false; } } return true; } }