Skip to content

Commit e14e340

Browse files
committed
Address normen662 comments.
- make sure to convert FieldKeyExpression#fieldName (which is internal) to user-facing name when constructing match candidates. - also, add tests for deeply nested (and repeated) structures with non-pb-compliant field names, and an index.
1 parent 43e6041 commit e14e340

File tree

7 files changed

+144
-28
lines changed

7 files changed

+144
-28
lines changed

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/FieldKeyExpression.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.apple.foundationdb.record.query.plan.cascades.KeyExpressionVisitor;
3434
import com.apple.foundationdb.record.query.plan.cascades.Quantifier;
3535
import com.apple.foundationdb.record.query.plan.cascades.expressions.ExplodeExpression;
36+
import com.apple.foundationdb.record.util.ProtoUtils;
3637
import com.google.common.collect.ImmutableList;
3738
import com.google.protobuf.Descriptors;
3839
import com.google.protobuf.Message;
@@ -57,6 +58,13 @@
5758
public class FieldKeyExpression extends BaseKeyExpression implements AtomKeyExpression, KeyExpressionWithoutChildren {
5859
private static final ObjectPlanHash BASE_HASH = new ObjectPlanHash("Field-Key-Expression");
5960

61+
/**
62+
* The internal field name used in the underlying protobuf message. This name may differ from the user-visible
63+
* identifier to ensure compliance with protobuf field naming conventions. When working with query planning or
64+
* user-facing operations, use {@link ProtoUtils#toUserIdentifier(String)} to convert this to the user-visible
65+
* form. However, when constructing physical operators that directly interact with stored protobuf messages,
66+
* this internal name should be used as-is.
67+
*/
6068
@Nonnull
6169
private final String fieldName;
6270
@Nonnull
@@ -216,7 +224,7 @@ public <S extends KeyExpressionVisitor.State, R> R expand(@Nonnull final KeyExpr
216224
public Quantifier.ForEach explodeField(@Nonnull Quantifier.ForEach baseQuantifier, @Nonnull List<String> fieldNamePrefix) {
217225
final List<String> fieldNames = ImmutableList.<String>builder()
218226
.addAll(fieldNamePrefix)
219-
.add(fieldName)
227+
.add(ProtoUtils.toUserIdentifier(fieldName))
220228
.build();
221229
switch (fanType) {
222230
case FanOut:

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/KeyExpressionExpansionVisitor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ public GraphExpansion visitExpression(@Nonnull final NestingKeyExpression nestin
242242
case None:
243243
List<String> newPrefix = ImmutableList.<String>builder()
244244
.addAll(fieldNamePrefix)
245-
.add(parent.getFieldName())
245+
.add(ProtoUtils.toUserIdentifier((parent.getFieldName())))
246246
.build();
247247
if (NullableArrayTypeUtils.isArrayWrapper(nestingKeyExpression)) {
248248
final RecordKeyExpressionProto.KeyExpression childProto = nestingKeyExpression.getChild().toKeyExpression();

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/ScalarTranslationVisitor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,10 @@ public Value visitExpression(@Nonnull final NestingKeyExpression nestingKeyExpre
170170
final ScalarVisitorState state = getCurrentState();
171171
final List<String> fieldNamePrefix = state.getFieldNamePrefix();
172172
final KeyExpression child = nestingKeyExpression.getChild();
173+
final String parentFieldName = ProtoUtils.toUserIdentifier(parent.getFieldName());
173174
final List<String> newPrefix = ImmutableList.<String>builder()
174175
.addAll(fieldNamePrefix)
175-
.add(parent.getFieldName())
176+
.add(parentFieldName)
176177
.build();
177178
// TODO resolve type
178179
return pop(child.expand(push(state.withFieldNamePrefix(newPrefix))));

yaml-tests/src/test/java/YamlIntegrationTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ public void castTests(YamlTest.Runner runner) throws Exception {
350350
* @see MetaDataExportUtilityTests#createValidIdentifiersMetaData() for how the custom meta-data is generated
351351
*/
352352
@TestTemplate
353+
@MaintainYamlTestConfig(YamlTestConfigFilters.CORRECT_EXPLAIN_AND_METRICS)
353354
public void validIdentifierTests(YamlTest.Runner runner) throws Exception {
354355
runner.runYamsql("valid-identifiers.yamsql");
355356
}

yaml-tests/src/test/resources/valid-identifiers.metrics.binpb

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,56 @@
1-
�
1+
�2
2+
�
3+
all-tests�EXPLAIN select t.id from "foo.table$nested.repeated" as t, t."level0.field1" as b where exists (select "level2$array.field.1" from b."level1$field.1" where "level2$array.field.1" = 10)�0
4+
���O� ���<( 0���8*@�SCAN(<,>) | TFILTER foo__2table__1nested__2repeated | FLATMAP q0 -> { EXPLODE q0.level0.field1 | FLATMAP q1 -> { EXPLODE q1.level1$field.1 | FILTER _.level2$array.field.1 EQUALS promote(@c27 AS LONG) | MAP (_.level2$array.field.1 AS level2$array.field.1) | DEFAULT NULL | FILTER _ NOT_NULL AS q2 RETURN (1 AS _0) } AS q3 RETURN (q0.ID AS ID) }�-digraph G {
5+
fontname=courier;
6+
rankdir=BT;
7+
splines=polyline;
8+
1 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Nested Loop Join</td></tr><tr><td align="left">FLATMAP (q2.ID AS ID)</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID)" ];
9+
2 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Type Filter</td></tr><tr><td align="left">WHERE record IS [foo__2table__1nested__2repeated]</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, ARRAY(ARRAY(LONG AS level2$array.field.1, LONG AS level2$field.2) AS level1$field.1, LONG AS level2$field.1, LONG AS level2$field.2 AS level1$field.2) AS level0.field1)" ];
10+
3 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Scan</td></tr><tr><td align="left">range: &lt;-∞, ∞&gt;</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(RECORD)" ];
11+
4 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Primary Storage</td></tr><tr><td align="left">record types: [foo__2tableA, foo__1tableC, foo__2table__1nested, foo__2table__1nested__2repeated, my__1adjacency__1list, foo__2enum__2type, foo__2tableB, __foo__0tableD, foo__2tableE]</td></tr></table>> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(RECORD)" ];
12+
5 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Nested Loop Join</td></tr><tr><td align="left">FLATMAP (1 AS _0)</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(INT AS _0)" ];
13+
6 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Value Computation</td></tr><tr><td align="left">EXPLODE q2.level0.field1</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(ARRAY(LONG AS level2$array.field.1, LONG AS level2$field.2) AS level1$field.1, LONG AS level2$field.1, LONG AS level2$field.2 AS level1$field.2)" ];
14+
7 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Predicate Filter</td></tr><tr><td align="left">WHERE q10 NOT_NULL</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS level2$array.field.1)" ];
15+
8 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Value Computation</td></tr><tr><td align="left">FIRST $q10 OR NULL</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS level2$array.field.1)" ];
16+
9 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Value Computation</td></tr><tr><td align="left">MAP (q43.level2$array.field.1 AS level2$array.field.1)</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS level2$array.field.1)" ];
17+
10 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Predicate Filter</td></tr><tr><td align="left">WHERE q6.level2$array.field.1 EQUALS promote(@c27 AS LONG)</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS level2$array.field.1, LONG AS level2$field.2)" ];
18+
11 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Value Computation</td></tr><tr><td align="left">EXPLODE q4.level1$field.1</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS level2$array.field.1, LONG AS level2$field.2)" ];
19+
3 -> 2 [ label=<&nbsp;q47> label="q47" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
20+
4 -> 3 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
21+
2 -> 1 [ label=<&nbsp;q2> label="q2" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
22+
6 -> 5 [ label=<&nbsp;q4> label="q4" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
23+
7 -> 5 [ label=<&nbsp;q10> label="q10" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
24+
8 -> 7 [ label=<&nbsp;q10> label="q10" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
25+
9 -> 8 [ label=<&nbsp;q10> label="q10" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
26+
10 -> 9 [ label=<&nbsp;q43> label="q43" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
27+
11 -> 10 [ label=<&nbsp;q6> label="q6" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
28+
5 -> 1 [ label=<&nbsp;q51> label="q51" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
29+
{
30+
rank=same;
31+
rankDir=LR;
32+
6 -> 7 [ color="red" style="invis" ];
33+
}
34+
{
35+
rank=same;
36+
rankDir=LR;
37+
2 -> 5 [ color="red" style="invis" ];
38+
}
39+
}�
40+
r
41+
all-testseEXPLAIN select "level0.field1"."level1$field.1"."level2$field.1" from "foo.table$nested" where id = 1�
42+
����]r ���D(!0��84@�COVERING(foo.table$nested.idx <,> -> [ID: KEY[2], level0__2field1: [level1__1field__21: [level2__1field__21: KEY[0]]]]) | FILTER _.ID EQUALS promote(@c12 AS LONG) | MAP (_.level0.field1.level1$field.1.level2$field.1 AS level2$field.1)�digraph G {
43+
fontname=courier;
44+
rankdir=BT;
45+
splines=polyline;
46+
1 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Value Computation</td></tr><tr><td align="left">MAP (q49.level0.field1.level1$field.1.level2$field.1 AS level2$field.1)</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS level2$field.1)" ];
47+
2 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Predicate Filter</td></tr><tr><td align="left">WHERE q45.ID EQUALS promote(@c12 AS LONG)</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, LONG AS level2$field.1, LONG AS level2$field.2 AS level1$field.1, LONG AS level2$field.1, LONG AS level2$field.2 AS level1$field.2 AS level0.field1)" ];
48+
3 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Covering Index Scan</td></tr><tr><td align="left">range: &lt;-∞, ∞&gt;</td></tr></table>> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, LONG AS level2$field.1, LONG AS level2$field.2 AS level1$field.1, LONG AS level2$field.1, LONG AS level2$field.2 AS level1$field.2 AS level0.field1)" ];
49+
4 [ label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="8"><tr><td align="left">Index</td></tr><tr><td align="left">foo.table$nested.idx</td></tr></table>> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS ID, LONG AS level2$field.1, LONG AS level2$field.2 AS level1$field.1, LONG AS level2$field.1, LONG AS level2$field.2 AS level1$field.2 AS level0.field1)" ];
50+
3 -> 2 [ label=<&nbsp;q45> label="q45" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
51+
4 -> 3 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
52+
2 -> 1 [ label=<&nbsp;q49> label="q49" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ];
53+
}�
254
=
355
all-tests0EXPLAIN select "foo.tableA".* from "foo.tableA";�
456
�ϊ�5j ���&(10ĕ�8-@�COVERING(foo.tableA.idx <,> -> [foo__2tableA__2A1: KEY[0], foo__2tableA__2A2: KEY[1], foo__2tableA__2A3: KEY[2]]) | MAP (_.foo.tableA.A1 AS foo.tableA.A1, _.foo.tableA.A2 AS foo.tableA.A2, _.foo.tableA.A3 AS foo.tableA.A3)� digraph G {

yaml-tests/src/test/resources/valid-identifiers.metrics.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,33 @@
11
all-tests:
2+
- query: EXPLAIN select t.id from "foo.table$nested.repeated" as t, t."level0.field1"
3+
as b where exists (select "level2$array.field.1" from b."level1$field.1" where
4+
"level2$array.field.1" = 10)
5+
explain: SCAN(<,>) | TFILTER foo__2table__1nested__2repeated | FLATMAP q0 -> {
6+
EXPLODE q0.level0.field1 | FLATMAP q1 -> { EXPLODE q1.level1$field.1 | FILTER
7+
_.level2$array.field.1 EQUALS promote(@c27 AS LONG) | MAP (_.level2$array.field.1
8+
AS level2$array.field.1) | DEFAULT NULL | FILTER _ NOT_NULL AS q2 RETURN (1
9+
AS _0) } AS q3 RETURN (q0.ID AS ID) }
10+
task_count: 471
11+
task_total_time_ms: 165
12+
transform_count: 173
13+
transform_time_ms: 127
14+
transform_yield_count: 32
15+
insert_time_ms: 7
16+
insert_new_count: 42
17+
insert_reused_count: 5
18+
- query: EXPLAIN select "level0.field1"."level1$field.1"."level2$field.1" from "foo.table$nested"
19+
where id = 1
20+
explain: 'COVERING(foo.table$nested.idx <,> -> [ID: KEY[2], level0__2field1: [level1__1field__21:
21+
[level2__1field__21: KEY[0]]]]) | FILTER _.ID EQUALS promote(@c12 AS LONG)
22+
| MAP (_.level0.field1.level1$field.1.level2$field.1 AS level2$field.1)'
23+
task_count: 474
24+
task_total_time_ms: 196
25+
transform_count: 114
26+
transform_time_ms: 143
27+
transform_yield_count: 33
28+
insert_time_ms: 10
29+
insert_new_count: 52
30+
insert_reused_count: 6
231
- query: EXPLAIN select "foo.tableA".* from "foo.tableA";
332
explain: 'COVERING(foo.tableA.idx <,> -> [foo__2tableA__2A1: KEY[0], foo__2tableA__2A2:
433
KEY[1], foo__2tableA__2A3: KEY[2]]) | MAP (_.foo.tableA.A1 AS foo.tableA.A1,

0 commit comments

Comments
 (0)