org.elasticsearch.xpack.esql.plan.logical.Lookup Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of x-pack-esql Show documentation
Show all versions of x-pack-esql Show documentation
The plugin that powers ESQL for Elasticsearch
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
package org.elasticsearch.xpack.esql.plan.logical;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.xpack.esql.core.capabilities.Resolvables;
import org.elasticsearch.xpack.esql.core.expression.Attribute;
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.plan.logical.LogicalPlan;
import org.elasticsearch.xpack.esql.core.plan.logical.UnaryPlan;
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
import org.elasticsearch.xpack.esql.core.tree.Source;
import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput;
import org.elasticsearch.xpack.esql.io.stream.PlanStreamOutput;
import org.elasticsearch.xpack.esql.plan.logical.join.Join;
import org.elasticsearch.xpack.esql.plan.logical.join.JoinConfig;
import org.elasticsearch.xpack.esql.plan.logical.join.JoinType;
import org.elasticsearch.xpack.esql.plan.logical.local.LocalRelation;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Looks up values from the associated {@code tables}.
* The class is supposed to be substituted by a {@link Join}.
*/
public class Lookup extends UnaryPlan {
private final Expression tableName;
/**
* References to the input fields to match against the {@link #localRelation}.
*/
private final List matchFields;
// initialized during the analysis phase for output and validation
// afterward, it is converted into a Join (BinaryPlan) hence why here it is not a child
private final LocalRelation localRelation;
private List lazyOutput;
public Lookup(
Source source,
LogicalPlan child,
Expression tableName,
List matchFields,
@Nullable LocalRelation localRelation
) {
super(source, child);
this.tableName = tableName;
this.matchFields = matchFields;
this.localRelation = localRelation;
}
public Lookup(PlanStreamInput in) throws IOException {
super(Source.readFrom(in), in.readLogicalPlanNode());
this.tableName = in.readNamedWriteable(Expression.class);
this.matchFields = in.readNamedWriteableCollectionAsList(Attribute.class);
this.localRelation = in.readBoolean() ? new LocalRelation(in) : null;
}
public void writeTo(PlanStreamOutput out) throws IOException {
source().writeTo(out);
out.writeLogicalPlanNode(child());
out.writeNamedWriteable(tableName);
out.writeNamedWriteableCollection(matchFields);
if (localRelation == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
localRelation.writeTo(out);
}
}
public Expression tableName() {
return tableName;
}
public List matchFields() {
return matchFields;
}
public LocalRelation localRelation() {
return localRelation;
}
public JoinConfig joinConfig() {
List leftFields = new ArrayList<>(matchFields.size());
List rightFields = new ArrayList<>(matchFields.size());
List rhsOutput = Join.makeReference(localRelation.output());
for (Attribute lhs : matchFields) {
for (Attribute rhs : rhsOutput) {
if (lhs.name().equals(rhs.name())) {
leftFields.add(lhs);
rightFields.add(rhs);
break;
}
}
}
return new JoinConfig(JoinType.LEFT, matchFields, leftFields, rightFields);
}
@Override
public boolean expressionsResolved() {
return tableName.resolved() && Resolvables.resolved(matchFields) && localRelation != null;
}
@Override
public UnaryPlan replaceChild(LogicalPlan newChild) {
return new Lookup(source(), newChild, tableName, matchFields, localRelation);
}
@Override
protected NodeInfo extends LogicalPlan> info() {
return NodeInfo.create(this, Lookup::new, child(), tableName, matchFields, localRelation);
}
@Override
public List output() {
if (lazyOutput == null) {
if (localRelation == null) {
throw new IllegalStateException("Cannot determine output of LOOKUP with unresolved table");
}
lazyOutput = Join.computeOutput(child().output(), localRelation.output(), joinConfig());
}
return lazyOutput;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (super.equals(o) == false) {
return false;
}
Lookup lookup = (Lookup) o;
return Objects.equals(tableName, lookup.tableName)
&& Objects.equals(matchFields, lookup.matchFields)
&& Objects.equals(localRelation, lookup.localRelation);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), tableName, matchFields, localRelation);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy