Skip to content

Commit b923d9d

Browse files
authored
Derive entity path for OutputColumnof a lens based on input Chunk (#11481)
### Related * Follow up of #11394. * Part of RR-2554. ### What This derives the entity path for the output column from the input column's chunk, unless specified otherwise. This saves a lot of duplicated code, because now multiple input entities can be treated at once using the `EntityPathFilter` of the input column.
1 parent 7ab3463 commit b923d9d

File tree

3 files changed

+52
-24
lines changed

3 files changed

+52
-24
lines changed

crates/top/re_sdk/src/lenses/ast.rs

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ pub struct InputColumn {
1818
}
1919

2020
pub struct OutputColumn {
21-
pub entity_path: EntityPath,
21+
/// The target entity path for this column.
22+
///
23+
/// If `None`, the entity path of the output column will be set to the matched entity path of the input column.
24+
pub new_entity_path: Option<EntityPath>,
2225
pub component_descr: ComponentDescriptor,
2326
pub ops: Vec<Op>,
2427
// TODO(grtlr): It would be much nicer if static could be inferred from the output of the operations?
@@ -66,7 +69,7 @@ impl Op {
6669

6770
/// Ignores any input and returns a constant `ListArray`.
6871
///
69-
/// Mostl commonly used with [`LensBuilder::add_static_output_column`].
72+
/// Commonly used with [`LensBuilder::add_static_output_column_entity`].
7073
/// When used in non-static columns this function will _not_ guarantee the correct amount of rows.
7174
pub fn constant(value: ListArray) -> Self {
7275
Self::func(move |_| Ok(value.clone()))
@@ -132,8 +135,13 @@ impl Lens {
132135

133136
let mut builders = ahash::HashMap::default();
134137
for output in &self.outputs {
138+
let entity_path = output
139+
.new_entity_path
140+
.as_ref()
141+
.unwrap_or(chunk.entity_path());
142+
135143
let components = builders
136-
.entry((output.entity_path.clone(), output.is_static))
144+
.entry((entity_path.clone(), output.is_static))
137145
.or_insert_with(ChunkComponents::default);
138146

139147
if components.contains_component(&output.component_descr) {
@@ -150,7 +158,7 @@ impl Lens {
150158
re_log::error!(
151159
"Lens operation '{:?}' failed for output column '{}' on entity '{}': {err}",
152160
op,
153-
output.entity_path,
161+
entity_path,
154162
output.component_descr.component
155163
);
156164
return vec![];
@@ -205,14 +213,35 @@ impl LensBuilder {
205213

206214
/// Can be used to define one or more output columns that are derived from the
207215
/// component specified via [`Self::for_input_column`].
216+
///
217+
/// The output column will live on the same entity path as the input column.
208218
pub fn add_output_column(
219+
mut self,
220+
component_descr: ComponentDescriptor,
221+
ops: impl IntoIterator<Item = Op>,
222+
) -> Self {
223+
let column = OutputColumn {
224+
new_entity_path: None,
225+
component_descr,
226+
ops: ops.into_iter().collect(),
227+
is_static: false,
228+
};
229+
self.0.outputs.push(column);
230+
self
231+
}
232+
233+
/// Can be used to define one or more output columns that are derived from the
234+
/// component specified via [`Self::for_input_column`].
235+
///
236+
/// The output column will live on the same entity path as the input column.
237+
pub fn add_output_column_entity(
209238
mut self,
210239
entity_path: impl Into<EntityPath>,
211240
component_descr: ComponentDescriptor,
212241
ops: impl IntoIterator<Item = Op>,
213242
) -> Self {
214243
let column = OutputColumn {
215-
entity_path: entity_path.into(),
244+
new_entity_path: Some(entity_path.into()),
216245
component_descr,
217246
ops: ops.into_iter().collect(),
218247
is_static: false,
@@ -224,15 +253,19 @@ impl LensBuilder {
224253
/// Can be used to define one or more static output columns that are derived from the
225254
/// component specified via [`Self::for_input_column`].
226255
///
256+
/// The output column will live on the same entity path as the input column.
257+
///
227258
/// In most cases, static columns should have a single row only.
228-
pub fn add_static_output_column(
259+
// TODO(grtlr): We don't provide a non-entity version of this method, because it is
260+
// likely to change again anyway.
261+
pub fn add_static_output_column_entity(
229262
mut self,
230263
entity_path: impl Into<EntityPath>,
231264
component_descr: ComponentDescriptor,
232265
ops: impl IntoIterator<Item = Op>,
233266
) -> Self {
234267
let column = OutputColumn {
235-
entity_path: entity_path.into(),
268+
new_entity_path: Some(entity_path.into()),
236269
component_descr,
237270
ops: ops.into_iter().collect(),
238271
is_static: true,
@@ -449,7 +482,7 @@ mod test {
449482

450483
let destructure =
451484
Lens::for_input_column(EntityPathFilter::parse_forgiving("nullability"), "structs")
452-
.add_output_column(
485+
.add_output_column_entity(
453486
"nullability/a",
454487
Scalars::descriptor_scalars(),
455488
[Op::access_field("a"), Op::cast(DataType::Float64)],
@@ -474,7 +507,7 @@ mod test {
474507

475508
let destructure =
476509
Lens::for_input_column(EntityPathFilter::parse_forgiving("nullability"), "structs")
477-
.add_output_column(
510+
.add_output_column_entity(
478511
"nullability/b",
479512
Scalars::descriptor_scalars(),
480513
[Op::access_field("b")],
@@ -517,13 +550,8 @@ mod test {
517550

518551
let count =
519552
Lens::for_input_column(EntityPathFilter::parse_forgiving("nullability"), "strings")
553+
.add_output_column(ComponentDescriptor::partial("counts"), [Op::func(count_fn)])
520554
.add_output_column(
521-
"nullability/b_count",
522-
ComponentDescriptor::partial("counts"),
523-
[Op::func(count_fn)],
524-
)
525-
.add_output_column(
526-
"nullability/b_count",
527555
ComponentDescriptor::partial("original"),
528556
[], // no operations
529557
)
@@ -558,12 +586,12 @@ mod test {
558586

559587
let static_lens =
560588
Lens::for_input_column(EntityPathFilter::parse_forgiving("nullability"), "strings")
561-
.add_static_output_column(
589+
.add_static_output_column_entity(
562590
"nullability/static",
563591
ComponentDescriptor::partial("static_metadata_a"),
564592
[Op::constant(metadata_builder_a.finish())],
565593
)
566-
.add_static_output_column(
594+
.add_static_output_column_entity(
567595
"nullability/static",
568596
ComponentDescriptor::partial("static_metadata_b"),
569597
[Op::constant(metadata_builder_b.finish())],

crates/top/re_sdk/src/lenses/snapshots/re_sdk__lenses__ast__test__inner_count.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ expression: "format!(\"{chunk:-240}\")"
44
---
55
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
66
METADATA: │
7-
* entity_path: /nullability/b_count
7+
* entity_path: /nullability
88
* heap_size_bytes: [**REDACTED**] │
99
* id: [**REDACTED**] │
1010
* version: [**REDACTED**] │

examples/rust/lenses/src/main.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ fn lens_flag() -> anyhow::Result<Lens> {
5353
.unwrap();
5454

5555
let lens = Lens::for_input_column("/flag".parse()?, "example:Flag:flag")
56-
.add_output_column("/flag", Scalars::descriptor_scalars(), [Op::func(step_fn)])
57-
.add_static_output_column(
56+
.add_output_column(Scalars::descriptor_scalars(), [Op::func(step_fn)])
57+
.add_static_output_column_entity(
5858
"/flag",
5959
series_points.descriptor,
6060
[Op::constant(series_points.list_array)],
6161
)
62-
.add_static_output_column(
62+
.add_static_output_column_entity(
6363
"/flag",
6464
series_lines.descriptor,
6565
[Op::constant(series_lines.list_array)],
@@ -73,16 +73,16 @@ fn main() -> anyhow::Result<()> {
7373
re_log::setup_logging();
7474

7575
let instruction = Lens::for_input_column("/instructions".parse()?, "example:Instruction:text")
76-
.add_output_column("instructions", TextDocument::descriptor_text(), [])
76+
.add_output_column(TextDocument::descriptor_text(), [])
7777
.build();
7878

7979
let destructure = Lens::for_input_column("/nested".parse()?, "example:Nested:payload")
80-
.add_output_column(
80+
.add_output_column_entity(
8181
"nested/a",
8282
Scalars::descriptor_scalars(),
8383
[Op::access_field("a"), Op::cast(DataType::Float64)],
8484
)
85-
.add_output_column(
85+
.add_output_column_entity(
8686
"nested/b",
8787
Scalars::descriptor_scalars(),
8888
[Op::access_field("b")],

0 commit comments

Comments
 (0)