Skip to content

Commit 068f51d

Browse files
authored
Reapply "ESQL: Remove parent from FieldAttribute (#112881)" (#115006) (#115007) (#115035)
This reverts commit 17ecb66 and reapplies #112881 once the previous, non-backported transport version bump is dealt with.
1 parent 6a8d280 commit 068f51d

File tree

30 files changed

+323
-134
lines changed

30 files changed

+323
-134
lines changed

docs/changelog/112881.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 112881
2+
summary: "ESQL: Remove parent from `FieldAttribute`"
3+
area: ES|QL
4+
type: enhancement
5+
issues: []

server/src/main/java/org/elasticsearch/TransportVersions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ static TransportVersion def(int id) {
176176
public static final TransportVersion CONVERT_FAILURE_STORE_OPTIONS_TO_SELECTOR_OPTIONS_INTERNALLY = def(8_772_00_0);
177177
public static final TransportVersion REMOVE_MIN_COMPATIBLE_SHARD_NODE = def(8_773_00_0);
178178
public static final TransportVersion REVERT_REMOVE_MIN_COMPATIBLE_SHARD_NODE = def(8_774_00_0);
179+
public static final TransportVersion ESQL_FIELD_ATTRIBUTE_PARENT_SIMPLIFIED = def(8_775_00_0);
179180

180181
/*
181182
* STOP! READ THIS FIRST! No, really,

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Alias.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
1010
import org.elasticsearch.common.io.stream.StreamInput;
1111
import org.elasticsearch.common.io.stream.StreamOutput;
12+
import org.elasticsearch.core.Nullable;
1213
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
1314
import org.elasticsearch.xpack.esql.core.tree.Source;
1415
import org.elasticsearch.xpack.esql.core.type.DataType;
@@ -42,11 +43,11 @@ public Alias(Source source, String name, Expression child) {
4243
this(source, name, child, null);
4344
}
4445

45-
public Alias(Source source, String name, Expression child, NameId id) {
46+
public Alias(Source source, String name, Expression child, @Nullable NameId id) {
4647
this(source, name, child, id, false);
4748
}
4849

49-
public Alias(Source source, String name, Expression child, NameId id, boolean synthetic) {
50+
public Alias(Source source, String name, Expression child, @Nullable NameId id, boolean synthetic) {
5051
super(source, name, singletonList(child), id, synthetic);
5152
this.child = child;
5253
}
@@ -55,7 +56,7 @@ public Alias(Source source, String name, Expression child, NameId id, boolean sy
5556
/**
5657
* Old constructor from when this had a qualifier string. Still needed to not break serialization.
5758
*/
58-
private Alias(Source source, String name, String qualifier, Expression child, NameId id, boolean synthetic) {
59+
private Alias(Source source, String name, String qualifier, Expression child, @Nullable NameId id, boolean synthetic) {
5960
this(source, name, child, id, synthetic);
6061
}
6162

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Attribute.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package org.elasticsearch.xpack.esql.core.expression;
88

99
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
10+
import org.elasticsearch.core.Nullable;
1011
import org.elasticsearch.xpack.esql.core.tree.Source;
1112
import org.elasticsearch.xpack.esql.core.type.DataType;
1213

@@ -41,15 +42,15 @@ public static List<NamedWriteableRegistry.Entry> getNamedWriteables() {
4142
// can the attr be null - typically used in JOINs
4243
private final Nullability nullability;
4344

44-
public Attribute(Source source, String name, NameId id) {
45+
public Attribute(Source source, String name, @Nullable NameId id) {
4546
this(source, name, Nullability.TRUE, id);
4647
}
4748

48-
public Attribute(Source source, String name, Nullability nullability, NameId id) {
49+
public Attribute(Source source, String name, Nullability nullability, @Nullable NameId id) {
4950
this(source, name, nullability, id, false);
5051
}
5152

52-
public Attribute(Source source, String name, Nullability nullability, NameId id, boolean synthetic) {
53+
public Attribute(Source source, String name, Nullability nullability, @Nullable NameId id, boolean synthetic) {
5354
super(source, name, emptyList(), id, synthetic);
5455
this.nullability = nullability;
5556
}

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java

Lines changed: 63 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,25 @@
66
*/
77
package org.elasticsearch.xpack.esql.core.expression;
88

9+
import org.elasticsearch.TransportVersions;
910
import org.elasticsearch.common.Strings;
1011
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
1112
import org.elasticsearch.common.io.stream.StreamInput;
1213
import org.elasticsearch.common.io.stream.StreamOutput;
14+
import org.elasticsearch.core.Nullable;
1315
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
1416
import org.elasticsearch.xpack.esql.core.tree.Source;
1517
import org.elasticsearch.xpack.esql.core.type.DataType;
1618
import org.elasticsearch.xpack.esql.core.type.EsField;
1719
import org.elasticsearch.xpack.esql.core.util.PlanStreamInput;
1820
import org.elasticsearch.xpack.esql.core.util.PlanStreamOutput;
19-
import org.elasticsearch.xpack.esql.core.util.StringUtils;
2021

2122
import java.io.IOException;
2223
import java.util.Objects;
2324

25+
import static org.elasticsearch.xpack.esql.core.util.PlanStreamInput.readCachedStringWithVersionCheck;
26+
import static org.elasticsearch.xpack.esql.core.util.PlanStreamOutput.writeCachedStringWithVersionCheck;
27+
2428
/**
2529
* Attribute for an ES field.
2630
* To differentiate between the different type of fields this class offers:
@@ -37,32 +41,31 @@ public class FieldAttribute extends TypedAttribute {
3741
FieldAttribute::readFrom
3842
);
3943

40-
private final FieldAttribute parent;
41-
private final String path;
44+
private final String parentName;
4245
private final EsField field;
4346

4447
public FieldAttribute(Source source, String name, EsField field) {
4548
this(source, null, name, field);
4649
}
4750

48-
public FieldAttribute(Source source, FieldAttribute parent, String name, EsField field) {
49-
this(source, parent, name, field, Nullability.TRUE, null, false);
51+
public FieldAttribute(Source source, @Nullable String parentName, String name, EsField field) {
52+
this(source, parentName, name, field, Nullability.TRUE, null, false);
5053
}
5154

52-
public FieldAttribute(Source source, FieldAttribute parent, String name, EsField field, boolean synthetic) {
53-
this(source, parent, name, field, Nullability.TRUE, null, synthetic);
55+
public FieldAttribute(Source source, @Nullable String parentName, String name, EsField field, boolean synthetic) {
56+
this(source, parentName, name, field, Nullability.TRUE, null, synthetic);
5457
}
5558

5659
public FieldAttribute(
5760
Source source,
58-
FieldAttribute parent,
61+
@Nullable String parentName,
5962
String name,
6063
EsField field,
6164
Nullability nullability,
62-
NameId id,
65+
@Nullable NameId id,
6366
boolean synthetic
6467
) {
65-
this(source, parent, name, field.getDataType(), field, nullability, id, synthetic);
68+
this(source, parentName, name, field.getDataType(), field, nullability, id, synthetic);
6669
}
6770

6871
/**
@@ -71,17 +74,16 @@ public FieldAttribute(
7174
*/
7275
FieldAttribute(
7376
Source source,
74-
FieldAttribute parent,
77+
@Nullable String parentName,
7578
String name,
7679
DataType type,
7780
EsField field,
7881
Nullability nullability,
79-
NameId id,
82+
@Nullable NameId id,
8083
boolean synthetic
8184
) {
8285
super(source, name, type, nullability, id, synthetic);
83-
this.path = parent != null ? parent.name() : StringUtils.EMPTY;
84-
this.parent = parent;
86+
this.parentName = parentName;
8587
this.field = field;
8688
}
8789

@@ -91,16 +93,16 @@ public FieldAttribute(
9193
*/
9294
private FieldAttribute(
9395
Source source,
94-
FieldAttribute parent,
96+
@Nullable String parentName,
9597
String name,
9698
DataType type,
9799
EsField field,
98-
String qualifier,
100+
@Nullable String qualifier,
99101
Nullability nullability,
100-
NameId id,
102+
@Nullable NameId id,
101103
boolean synthetic
102104
) {
103-
this(source, parent, name, type, field, nullability, id, synthetic);
105+
this(source, parentName, name, type, field, nullability, id, synthetic);
104106
}
105107

106108
private FieldAttribute(StreamInput in) throws IOException {
@@ -114,8 +116,8 @@ private FieldAttribute(StreamInput in) throws IOException {
114116
*/
115117
this(
116118
Source.readFrom((StreamInput & PlanStreamInput) in),
117-
in.readOptionalWriteable(FieldAttribute::readFrom),
118-
((PlanStreamInput) in).readCachedString(),
119+
readParentName(in),
120+
readCachedStringWithVersionCheck(in),
119121
DataType.readFrom(in),
120122
EsField.readFrom(in),
121123
in.readOptionalString(),
@@ -129,8 +131,8 @@ private FieldAttribute(StreamInput in) throws IOException {
129131
public void writeTo(StreamOutput out) throws IOException {
130132
if (((PlanStreamOutput) out).writeAttributeCacheHeader(this)) {
131133
Source.EMPTY.writeTo(out);
132-
out.writeOptionalWriteable(parent);
133-
((PlanStreamOutput) out).writeCachedString(name());
134+
writeParentName(out);
135+
writeCachedStringWithVersionCheck(out, name());
134136
dataType().writeTo(out);
135137
field.writeTo(out);
136138
// We used to write the qualifier here. We can still do if needed in the future.
@@ -145,22 +147,49 @@ public static FieldAttribute readFrom(StreamInput in) throws IOException {
145147
return ((PlanStreamInput) in).readAttributeWithCache(FieldAttribute::new);
146148
}
147149

150+
private void writeParentName(StreamOutput out) throws IOException {
151+
if (out.getTransportVersion().onOrAfter(TransportVersions.ESQL_FIELD_ATTRIBUTE_PARENT_SIMPLIFIED)) {
152+
((PlanStreamOutput) out).writeOptionalCachedString(parentName);
153+
} else {
154+
// Previous versions only used the parent field attribute to retrieve the parent's name, so we can use just any
155+
// fake FieldAttribute here as long as the name is correct.
156+
FieldAttribute fakeParent = parentName() == null ? null : new FieldAttribute(Source.EMPTY, parentName(), field());
157+
out.writeOptionalWriteable(fakeParent);
158+
}
159+
}
160+
161+
private static String readParentName(StreamInput in) throws IOException {
162+
if (in.getTransportVersion().onOrAfter(TransportVersions.ESQL_FIELD_ATTRIBUTE_PARENT_SIMPLIFIED)) {
163+
return ((PlanStreamInput) in).readOptionalCachedString();
164+
}
165+
166+
FieldAttribute parent = in.readOptionalWriteable(FieldAttribute::readFrom);
167+
return parent == null ? null : parent.name();
168+
}
169+
148170
@Override
149171
public String getWriteableName() {
150172
return ENTRY.name;
151173
}
152174

153175
@Override
154176
protected NodeInfo<FieldAttribute> info() {
155-
return NodeInfo.create(this, FieldAttribute::new, parent, name(), dataType(), field, (String) null, nullable(), id(), synthetic());
156-
}
157-
158-
public FieldAttribute parent() {
159-
return parent;
177+
return NodeInfo.create(
178+
this,
179+
FieldAttribute::new,
180+
parentName,
181+
name(),
182+
dataType(),
183+
field,
184+
(String) null,
185+
nullable(),
186+
id(),
187+
synthetic()
188+
);
160189
}
161190

162-
public String path() {
163-
return path;
191+
public String parentName() {
192+
return parentName;
164193
}
165194

166195
/**
@@ -174,7 +203,7 @@ public String fieldName() {
174203
if ((synthetic() || name().startsWith(SYNTHETIC_ATTRIBUTE_NAME_PREFIX)) == false) {
175204
return name();
176205
}
177-
return Strings.hasText(path) ? path + "." + field.getName() : field.getName();
206+
return Strings.hasText(parentName) ? parentName + "." + field.getName() : field.getName();
178207
}
179208

180209
public EsField.Exact getExactInfo() {
@@ -190,13 +219,13 @@ public FieldAttribute exactAttribute() {
190219
}
191220

192221
private FieldAttribute innerField(EsField type) {
193-
return new FieldAttribute(source(), this, name() + "." + type.getName(), type, nullable(), id(), synthetic());
222+
return new FieldAttribute(source(), name(), name() + "." + type.getName(), type, nullable(), id(), synthetic());
194223
}
195224

196225
@Override
197226
protected Attribute clone(Source source, String name, DataType type, Nullability nullability, NameId id, boolean synthetic) {
198227
// Ignore `type`, this must be the same as the field's type.
199-
return new FieldAttribute(source, parent, name, field, nullability, id, synthetic);
228+
return new FieldAttribute(source, parentName, name, field, nullability, id, synthetic);
200229
}
201230

202231
@Override
@@ -206,13 +235,13 @@ public Attribute withDataType(DataType type) {
206235

207236
@Override
208237
public int hashCode() {
209-
return Objects.hash(super.hashCode(), path, field);
238+
return Objects.hash(super.hashCode(), parentName, field);
210239
}
211240

212241
@Override
213242
public boolean equals(Object obj) {
214243
return super.equals(obj)
215-
&& Objects.equals(path, ((FieldAttribute) obj).path)
244+
&& Objects.equals(parentName, ((FieldAttribute) obj).parentName)
216245
&& Objects.equals(field, ((FieldAttribute) obj).field);
217246
}
218247

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/MetadataAttribute.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
1111
import org.elasticsearch.common.io.stream.StreamInput;
1212
import org.elasticsearch.common.io.stream.StreamOutput;
13+
import org.elasticsearch.core.Nullable;
1314
import org.elasticsearch.core.Tuple;
1415
import org.elasticsearch.index.mapper.IdFieldMapper;
1516
import org.elasticsearch.index.mapper.IgnoredFieldMapper;
@@ -59,7 +60,7 @@ public MetadataAttribute(
5960
String name,
6061
DataType dataType,
6162
Nullability nullability,
62-
NameId id,
63+
@Nullable NameId id,
6364
boolean synthetic,
6465
boolean searchable
6566
) {
@@ -79,9 +80,9 @@ private MetadataAttribute(
7980
Source source,
8081
String name,
8182
DataType dataType,
82-
String qualifier,
83+
@Nullable String qualifier,
8384
Nullability nullability,
84-
NameId id,
85+
@Nullable NameId id,
8586
boolean synthetic,
8687
boolean searchable
8788
) {

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/NamedExpression.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import org.elasticsearch.common.io.stream.NamedWriteable;
1010
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
11+
import org.elasticsearch.core.Nullable;
1112
import org.elasticsearch.xpack.esql.core.tree.Source;
1213

1314
import java.util.ArrayList;
@@ -32,11 +33,11 @@ public static List<NamedWriteableRegistry.Entry> getNamedWriteables() {
3233
private final NameId id;
3334
private final boolean synthetic;
3435

35-
public NamedExpression(Source source, String name, List<Expression> children, NameId id) {
36+
public NamedExpression(Source source, String name, List<Expression> children, @Nullable NameId id) {
3637
this(source, name, children, id, false);
3738
}
3839

39-
public NamedExpression(Source source, String name, List<Expression> children, NameId id, boolean synthetic) {
40+
public NamedExpression(Source source, String name, List<Expression> children, @Nullable NameId id, boolean synthetic) {
4041
super(source, children);
4142
this.name = name;
4243
this.id = id == null ? new NameId() : id;

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/ReferenceAttribute.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
1010
import org.elasticsearch.common.io.stream.StreamInput;
1111
import org.elasticsearch.common.io.stream.StreamOutput;
12+
import org.elasticsearch.core.Nullable;
1213
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
1314
import org.elasticsearch.xpack.esql.core.tree.Source;
1415
import org.elasticsearch.xpack.esql.core.type.DataType;
@@ -31,7 +32,14 @@ public ReferenceAttribute(Source source, String name, DataType dataType) {
3132
this(source, name, dataType, Nullability.FALSE, null, false);
3233
}
3334

34-
public ReferenceAttribute(Source source, String name, DataType dataType, Nullability nullability, NameId id, boolean synthetic) {
35+
public ReferenceAttribute(
36+
Source source,
37+
String name,
38+
DataType dataType,
39+
Nullability nullability,
40+
@Nullable NameId id,
41+
boolean synthetic
42+
) {
3543
super(source, name, dataType, nullability, id, synthetic);
3644
}
3745

0 commit comments

Comments
 (0)