From 8fe76ad9830151f84dee52e72d694dc70172b5e2 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 12:46:39 +0200 Subject: [PATCH] New data APIs 15: one query crate to rule them all (#6036) There is now only one way to query data: `re_query` (well you can still query the datastore directly if you're a monster, but that's for another PR). All queries go through both the query cache and the deserialization cache. There will be a follow-up PR to disable the deserialization cache for specific components. Most of this is just (re)moving stuff around except for the last two commits which take care of porting the cached test suites since they cannot depend on uncached APIs to do comparisons anymore. - Closes #6018 - Closes https://github.com/rerun-io/rerun/issues/3320 --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - #5990 - #5992 - #5993 - #5994 - #6035 - #6036 - #6037 Builds on top of the static data PR series: - #5534 --- ARCHITECTURE.md | 1 - Cargo.lock | 75 +- Cargo.toml | 2 - crates/re_data_ui/src/component.rs | 6 +- .../re_data_ui/src/component_ui_registry.rs | 4 +- crates/re_data_ui/src/editors.rs | 20 +- crates/re_entity_db/Cargo.toml | 5 +- crates/re_entity_db/src/entity_db.rs | 28 +- crates/re_entity_db/src/lib.rs | 4 +- crates/re_query/Cargo.toml | 62 +- crates/re_query/README.md | 2 +- .../benches/flat_vec_deque.rs | 2 +- .../benches/latest_at.rs | 8 +- crates/re_query/benches/query_benchmark.rs | 313 ------- .../examples/latest_at.rs | 15 +- .../examples/latest_at_archetype.rs | 8 +- .../examples/range.rs | 16 +- crates/re_query/src/archetype_view.rs | 669 -------------- .../src/bin/clamped_zip.rs | 2 +- .../src/bin/range_zip.rs | 2 +- .../{re_query_cache => re_query}/src/cache.rs | 0 .../src/cache_stats.rs | 0 .../src/clamped_zip/.gitattributes | 0 .../src/clamped_zip/generated.rs | 2 +- .../src/clamped_zip/mod.rs | 0 .../src/flat_vec_deque.rs | 0 .../src/latest_at/helpers.rs | 20 +- crates/re_query/src/latest_at/mod.rs | 10 + .../src/latest_at/query.rs | 17 +- .../src/latest_at/results.rs | 48 +- .../src/latest_at/to_archetype/.gitattributes | 0 .../to_archetype/annotation_context.rs | 5 +- .../src/latest_at/to_archetype/arrows2d.rs | 5 +- .../src/latest_at/to_archetype/arrows3d.rs | 5 +- .../src/latest_at/to_archetype/asset3d.rs | 5 +- .../src/latest_at/to_archetype/background.rs | 5 +- .../src/latest_at/to_archetype/bar_chart.rs | 5 +- .../src/latest_at/to_archetype/boxes2d.rs | 5 +- .../src/latest_at/to_archetype/boxes3d.rs | 5 +- .../src/latest_at/to_archetype/clear.rs | 5 +- .../to_archetype/container_blueprint.rs | 5 +- .../src/latest_at/to_archetype/depth_image.rs | 5 +- .../to_archetype/disconnected_space.rs | 5 +- .../src/latest_at/to_archetype/image.rs | 5 +- .../latest_at/to_archetype/line_strips2d.rs | 5 +- .../latest_at/to_archetype/line_strips3d.rs | 5 +- .../src/latest_at/to_archetype/mesh3d.rs | 5 +- .../src/latest_at/to_archetype/mod.rs | 0 .../latest_at/to_archetype/panel_blueprint.rs | 5 +- .../src/latest_at/to_archetype/pinhole.rs | 5 +- .../src/latest_at/to_archetype/plot_legend.rs | 5 +- .../src/latest_at/to_archetype/points2d.rs | 5 +- .../src/latest_at/to_archetype/points3d.rs | 5 +- .../src/latest_at/to_archetype/scalar.rs | 5 +- .../src/latest_at/to_archetype/scalar_axis.rs | 5 +- .../to_archetype/segmentation_image.rs | 5 +- .../src/latest_at/to_archetype/series_line.rs | 5 +- .../latest_at/to_archetype/series_point.rs | 5 +- .../to_archetype/space_view_blueprint.rs | 7 +- .../to_archetype/space_view_contents.rs | 7 +- .../src/latest_at/to_archetype/tensor.rs | 5 +- .../latest_at/to_archetype/text_document.rs | 5 +- .../src/latest_at/to_archetype/text_log.rs | 5 +- .../src/latest_at/to_archetype/transform3d.rs | 5 +- .../to_archetype/view_coordinates.rs | 5 +- .../to_archetype/viewport_blueprint.rs | 5 +- crates/re_query/src/lib.rs | 84 +- crates/{re_query2 => re_query}/src/promise.rs | 0 crates/re_query/src/query.rs | 269 ------ crates/re_query/src/range.rs | 170 ---- crates/re_query/src/range/mod.rs | 7 + .../src/range/query.rs | 17 +- .../src/range/results.rs | 88 +- .../src/range_zip/.gitattributes | 0 .../src/range_zip/generated.rs | 2 +- .../src/range_zip/mod.rs | 0 crates/re_query/src/util.rs | 143 --- .../src/visible_history.rs | 0 .../re_query/tests/archetype_query_tests.rs | 336 ------- .../re_query/tests/archetype_range_tests.rs | 675 -------------- .../re_query/tests/archetype_visit_tests.rs | 392 -------- crates/re_query/tests/latest_at.rs | 589 ++++++++++++ crates/re_query/tests/range.rs | 852 ++++++++++++++++++ crates/re_query/tests/store.rs | 73 -- crates/re_query2/Cargo.toml | 87 -- crates/re_query2/README.md | 5 - crates/re_query2/benches/latest_at.rs | 347 ------- crates/re_query2/examples/latest_at.rs | 128 --- crates/re_query2/examples/range.rs | 168 ---- crates/re_query2/src/latest_at/mod.rs | 5 - crates/re_query2/src/latest_at/query.rs | 40 - crates/re_query2/src/latest_at/results.rs | 224 ----- crates/re_query2/src/lib.rs | 81 -- crates/re_query2/src/range/mod.rs | 5 - crates/re_query2/src/range/query.rs | 38 - crates/re_query2/src/range/results.rs | 204 ----- crates/re_query2/tests/latest_at.rs | 217 ----- crates/re_query2/tests/range.rs | 496 ---------- crates/re_query_cache/Cargo.toml | 81 -- crates/re_query_cache/README.md | 10 - crates/re_query_cache/src/latest_at/mod.rs | 10 - crates/re_query_cache/src/lib.rs | 54 -- crates/re_query_cache/src/range/mod.rs | 8 - crates/re_query_cache/tests/latest_at.rs | 526 ----------- crates/re_query_cache/tests/range.rs | 586 ------------ crates/re_space_view/Cargo.toml | 1 - crates/re_space_view/src/space_view.rs | 2 +- .../re_space_view/src/space_view_contents.rs | 2 +- crates/re_space_view/src/sub_archetypes.rs | 6 +- crates/re_space_view/src/visual_time_range.rs | 2 +- crates/re_space_view_dataframe/Cargo.toml | 1 - crates/re_space_view_spatial/Cargo.toml | 1 - .../src/visualizers/arrows2d.rs | 4 +- .../src/visualizers/arrows3d.rs | 4 +- .../src/visualizers/assets3d.rs | 4 +- .../src/visualizers/boxes2d.rs | 4 +- .../src/visualizers/boxes3d.rs | 4 +- .../src/visualizers/entity_iterator.rs | 6 +- .../src/visualizers/images.rs | 4 +- .../src/visualizers/lines2d.rs | 4 +- .../src/visualizers/lines3d.rs | 4 +- .../src/visualizers/meshes.rs | 4 +- .../src/visualizers/mod.rs | 2 +- .../src/visualizers/points2d.rs | 4 +- .../src/visualizers/points3d.rs | 4 +- .../src/visualizers/results_ext.rs | 65 +- .../src/visualizer_system.rs | 4 +- crates/re_space_view_text_document/Cargo.toml | 1 - .../src/visualizer_system.rs | 2 +- crates/re_space_view_text_log/Cargo.toml | 2 +- .../src/visualizer_system.rs | 10 +- crates/re_space_view_time_series/Cargo.toml | 1 - .../src/line_visualizer_system.rs | 12 +- .../src/point_visualizer_system.rs | 8 +- .../src/codegen/rust/to_archetype.rs | 12 +- crates/re_viewer/Cargo.toml | 2 +- crates/re_viewer/src/lib.rs | 4 +- crates/re_viewer/src/ui/memory_panel.rs | 2 +- crates/re_viewer_context/Cargo.toml | 1 - .../src/component_ui_registry.rs | 12 +- crates/re_viewer_context/src/item.rs | 3 +- .../re_viewer_context/src/space_view/mod.rs | 3 - crates/re_viewer_context/src/store_hub.rs | 2 +- crates/re_viewport/src/container.rs | 2 +- crates/re_viewport/src/viewport_blueprint.rs | 2 +- examples/rust/custom_space_view/Cargo.toml | 2 +- .../color_coordinates_visualizer_system.rs | 12 +- scripts/lint.py | 6 - 148 files changed, 1904 insertions(+), 6865 deletions(-) rename crates/{re_query_cache => re_query}/benches/flat_vec_deque.rs (99%) rename crates/{re_query_cache => re_query}/benches/latest_at.rs (98%) delete mode 100644 crates/re_query/benches/query_benchmark.rs rename crates/{re_query_cache => re_query}/examples/latest_at.rs (89%) rename crates/{re_query_cache => re_query}/examples/latest_at_archetype.rs (92%) rename crates/{re_query_cache => re_query}/examples/range.rs (91%) delete mode 100644 crates/re_query/src/archetype_view.rs rename crates/{re_query2 => re_query}/src/bin/clamped_zip.rs (99%) rename crates/{re_query2 => re_query}/src/bin/range_zip.rs (99%) rename crates/{re_query_cache => re_query}/src/cache.rs (100%) rename crates/{re_query_cache => re_query}/src/cache_stats.rs (100%) rename crates/{re_query2 => re_query}/src/clamped_zip/.gitattributes (100%) rename crates/{re_query2 => re_query}/src/clamped_zip/generated.rs (99%) rename crates/{re_query2 => re_query}/src/clamped_zip/mod.rs (100%) rename crates/{re_query_cache => re_query}/src/flat_vec_deque.rs (100%) rename crates/{re_query_cache => re_query}/src/latest_at/helpers.rs (96%) create mode 100644 crates/re_query/src/latest_at/mod.rs rename crates/{re_query_cache => re_query}/src/latest_at/query.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/results.rs (85%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/.gitattributes (100%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/annotation_context.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/arrows2d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/arrows3d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/asset3d.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/background.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/bar_chart.rs (93%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/boxes2d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/boxes3d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/clear.rs (91%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/container_blueprint.rs (98%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/depth_image.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/disconnected_space.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/image.rs (93%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/line_strips2d.rs (97%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/line_strips3d.rs (97%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/mesh3d.rs (97%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/mod.rs (100%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/panel_blueprint.rs (93%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/pinhole.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/plot_legend.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/points2d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/points3d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/scalar.rs (91%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/scalar_axis.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/segmentation_image.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/series_line.rs (93%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/series_point.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/space_view_blueprint.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/space_view_contents.rs (91%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/tensor.rs (91%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/text_document.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/text_log.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/transform3d.rs (91%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/view_coordinates.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/viewport_blueprint.rs (97%) rename crates/{re_query2 => re_query}/src/promise.rs (100%) delete mode 100644 crates/re_query/src/query.rs delete mode 100644 crates/re_query/src/range.rs create mode 100644 crates/re_query/src/range/mod.rs rename crates/{re_query_cache => re_query}/src/range/query.rs (96%) rename crates/{re_query_cache => re_query}/src/range/results.rs (92%) rename crates/{re_query2 => re_query}/src/range_zip/.gitattributes (100%) rename crates/{re_query2 => re_query}/src/range_zip/generated.rs (99%) rename crates/{re_query2 => re_query}/src/range_zip/mod.rs (100%) delete mode 100644 crates/re_query/src/util.rs rename crates/{re_query2 => re_query}/src/visible_history.rs (100%) delete mode 100644 crates/re_query/tests/archetype_query_tests.rs delete mode 100644 crates/re_query/tests/archetype_range_tests.rs delete mode 100644 crates/re_query/tests/archetype_visit_tests.rs create mode 100644 crates/re_query/tests/latest_at.rs create mode 100644 crates/re_query/tests/range.rs delete mode 100644 crates/re_query/tests/store.rs delete mode 100644 crates/re_query2/Cargo.toml delete mode 100644 crates/re_query2/README.md delete mode 100644 crates/re_query2/benches/latest_at.rs delete mode 100644 crates/re_query2/examples/latest_at.rs delete mode 100644 crates/re_query2/examples/range.rs delete mode 100644 crates/re_query2/src/latest_at/mod.rs delete mode 100644 crates/re_query2/src/latest_at/query.rs delete mode 100644 crates/re_query2/src/latest_at/results.rs delete mode 100644 crates/re_query2/src/lib.rs delete mode 100644 crates/re_query2/src/range/mod.rs delete mode 100644 crates/re_query2/src/range/query.rs delete mode 100644 crates/re_query2/src/range/results.rs delete mode 100644 crates/re_query2/tests/latest_at.rs delete mode 100644 crates/re_query2/tests/range.rs delete mode 100644 crates/re_query_cache/Cargo.toml delete mode 100644 crates/re_query_cache/README.md delete mode 100644 crates/re_query_cache/src/latest_at/mod.rs delete mode 100644 crates/re_query_cache/src/lib.rs delete mode 100644 crates/re_query_cache/src/range/mod.rs delete mode 100644 crates/re_query_cache/tests/latest_at.rs delete mode 100644 crates/re_query_cache/tests/range.rs diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 0bc22487db3f..f7c54b5dd2da 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -149,7 +149,6 @@ Update instructions: |----------------------|--------------------------------------------------------------------------| | re_entity_db | In-memory storage of Rerun entities | | re_query | Querying data in the re_data_store | -| re_query_cache | Caching datastructures for re_query | | re_types | The built-in Rerun data types, component types, and archetypes. | | re_types_blueprint | The core traits and types that power Rerun's Blueprint sub-system. | | re_log_encoding | Helpers for encoding and transporting Rerun log messages | diff --git a/Cargo.lock b/Cargo.lock index b5a8526152b7..ac78976d7797 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1418,7 +1418,7 @@ version = "0.16.0-alpha.2" dependencies = [ "mimalloc", "re_crash_handler", - "re_query2", + "re_query", "re_sdk_comms", "re_viewer", ] @@ -4309,7 +4309,6 @@ dependencies = [ "re_log_encoding", "re_log_types", "re_query", - "re_query_cache", "re_smart_channel", "re_tracing", "re_types", @@ -4458,62 +4457,6 @@ dependencies = [ [[package]] name = "re_query" version = "0.16.0-alpha.2" -dependencies = [ - "backtrace", - "criterion", - "document-features", - "itertools 0.12.0", - "mimalloc", - "rand", - "re_arrow2", - "re_data_store", - "re_format", - "re_format_arrow", - "re_log", - "re_log_types", - "re_tracing", - "re_types", - "re_types_core", - "serde", - "similar-asserts", - "smallvec", - "thiserror", -] - -[[package]] -name = "re_query2" -version = "0.16.0-alpha.2" -dependencies = [ - "ahash", - "anyhow", - "backtrace", - "criterion", - "document-features", - "itertools 0.12.0", - "mimalloc", - "nohash-hasher", - "rand", - "re_arrow2", - "re_data_store", - "re_format", - "re_format_arrow", - "re_log", - "re_log_types", - "re_tracing", - "re_tuid", - "re_types", - "re_types_core", - "serde", - "similar-asserts", - "smallvec", - "static_assertions", - "thiserror", - "unindent", -] - -[[package]] -name = "re_query_cache" -version = "0.16.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -4527,18 +4470,22 @@ dependencies = [ "parking_lot", "paste", "rand", + "re_arrow2", "re_data_store", "re_error", "re_format", "re_log", "re_log_types", - "re_query2", "re_tracing", + "re_tuid", "re_types", "re_types_blueprint", "re_types_core", "seq-macro", "similar-asserts", + "static_assertions", + "thiserror", + "unindent", "web-time", ] @@ -4683,7 +4630,6 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", "re_tracing", "re_types", "re_types_core", @@ -4721,7 +4667,6 @@ dependencies = [ "re_entity_db", "re_log_types", "re_query", - "re_query_cache", "re_renderer", "re_tracing", "re_types_core", @@ -4754,7 +4699,6 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", "re_renderer", "re_space_view", "re_tracing", @@ -4801,7 +4745,6 @@ dependencies = [ "itertools 0.12.0", "re_data_store", "re_log", - "re_query", "re_renderer", "re_space_view", "re_tracing", @@ -4822,7 +4765,7 @@ dependencies = [ "re_entity_db", "re_log", "re_log_types", - "re_query_cache", + "re_query", "re_renderer", "re_tracing", "re_types", @@ -4843,7 +4786,6 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", "re_renderer", "re_space_view", "re_tracing", @@ -5059,7 +5001,7 @@ dependencies = [ "re_log_encoding", "re_log_types", "re_memory", - "re_query_cache", + "re_query", "re_renderer", "re_smart_channel", "re_space_view", @@ -5119,7 +5061,6 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", "re_renderer", "re_smart_channel", "re_string_interner", diff --git a/Cargo.toml b/Cargo.toml index d391fc4bcab3..778307ce3fa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,8 +46,6 @@ re_log_encoding = { path = "crates/re_log_encoding", version = "=0.16.0-alpha.2" re_log_types = { path = "crates/re_log_types", version = "=0.16.0-alpha.2", default-features = false } re_memory = { path = "crates/re_memory", version = "=0.16.0-alpha.2", default-features = false } re_query = { path = "crates/re_query", version = "=0.16.0-alpha.2", default-features = false } -re_query_cache = { path = "crates/re_query_cache", version = "=0.16.0-alpha.2", default-features = false } -re_query2 = { path = "crates/re_query2", version = "=0.16.0-alpha.2", default-features = false } re_renderer = { path = "crates/re_renderer", version = "=0.16.0-alpha.2", default-features = false } re_sdk = { path = "crates/re_sdk", version = "=0.16.0-alpha.2", default-features = false } re_sdk_comms = { path = "crates/re_sdk_comms", version = "=0.16.0-alpha.2", default-features = false } diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index 6c6e9a2fa4c6..1fe709c7ea2b 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -2,9 +2,7 @@ use std::sync::Arc; use egui::NumExt; -use re_entity_db::{ - external::re_query_cache::CachedLatestAtComponentResults, EntityPath, InstancePath, -}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityPath, InstancePath}; use re_types::ComponentName; use re_ui::SyntaxHighlighting as _; use re_viewer_context::{UiVerbosity, ViewerContext}; @@ -16,7 +14,7 @@ use crate::item_ui; pub struct EntityLatestAtResults { pub entity_path: EntityPath, pub component_name: ComponentName, - pub results: Arc, + pub results: Arc, } impl DataUi for EntityLatestAtResults { diff --git a/crates/re_data_ui/src/component_ui_registry.rs b/crates/re_data_ui/src/component_ui_registry.rs index 98e4afbf148d..19c92ed3c541 100644 --- a/crates/re_data_ui/src/component_ui_registry.rs +++ b/crates/re_data_ui/src/component_ui_registry.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb}; use re_log_types::{external::arrow2, EntityPath}; use re_types::external::arrow2::array::Utf8Array; use re_viewer_context::{ComponentUiRegistry, UiVerbosity, ViewerContext}; @@ -62,7 +62,7 @@ fn fallback_component_ui( _query: &LatestAtQuery, db: &EntityDb, _entity_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { // TODO(#5607): what should happen if the promise is still pending? diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index 61b96d4eade1..b22499105bce 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -2,7 +2,7 @@ use egui::NumExt as _; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb}; use re_log_types::EntityPath; use re_types::{ components::{ @@ -23,7 +23,7 @@ fn edit_color_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_color = component @@ -66,7 +66,7 @@ fn edit_text_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_text = component @@ -106,7 +106,7 @@ fn edit_name_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_text = component @@ -147,7 +147,7 @@ fn edit_scatter_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_scatter = component @@ -196,7 +196,7 @@ fn edit_radius_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_radius = component @@ -243,7 +243,7 @@ fn edit_marker_shape_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_marker = component @@ -329,7 +329,7 @@ fn edit_stroke_width_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_stroke_width = component @@ -376,7 +376,7 @@ fn edit_marker_size_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_marker_size = component @@ -425,7 +425,7 @@ fn register_editor<'a, C: Component + Loggable + 'static>( &EntityDb, &EntityPath, &EntityPath, - &CachedLatestAtComponentResults, + &LatestAtComponentResults, &re_types::components::InstanceKey, ), ) where diff --git a/crates/re_entity_db/Cargo.toml b/crates/re_entity_db/Cargo.toml index db210bcf7b48..178cc0f8e3ee 100644 --- a/crates/re_entity_db/Cargo.toml +++ b/crates/re_entity_db/Cargo.toml @@ -23,7 +23,7 @@ all-features = true default = [] ## Enable (de)serialization using serde. -serde = ["dep:serde", "dep:rmp-serde", "re_log_types/serde", "re_query/serde"] +serde = ["dep:serde", "dep:rmp-serde", "re_log_types/serde"] [dependencies] @@ -33,8 +33,7 @@ re_int_histogram.workspace = true re_log.workspace = true re_log_encoding = { workspace = true, features = ["decoder"] } re_log_types.workspace = true -re_query.workspace = true -re_query_cache = { workspace = true, features = ["to_archetype"] } +re_query = { workspace = true, features = ["to_archetype"] } re_smart_channel.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index 4d618e81a71a..2355ce9dfe1b 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -12,7 +12,7 @@ use re_log_types::{ EntityPathHash, LogMsg, RowId, SetStoreInfo, StoreId, StoreInfo, StoreKind, TimePoint, TimeRange, TimeRangeF, Timeline, }; -use re_query_cache::PromiseResult; +use re_query::PromiseResult; use re_types_core::{components::InstanceKey, Archetype, Loggable}; use crate::{ClearCascade, CompactedStoreEvents, Error, TimesPerTimeline}; @@ -117,10 +117,10 @@ pub struct EntityDb { data_store: DataStore, /// The active promise resolver for this DB. - resolver: re_query_cache::PromiseResolver, + resolver: re_query::PromiseResolver, /// Query caches for the data in [`Self::data_store`]. - query_caches: re_query_cache::Caches, + query_caches: re_query::Caches, stats: IngestionStatistics, } @@ -132,7 +132,7 @@ impl EntityDb { InstanceKey::name(), DataStoreConfig::default(), ); - let query_caches = re_query_cache::Caches::new(&data_store); + let query_caches = re_query::Caches::new(&data_store); Self { data_source: None, set_store_info: None, @@ -142,7 +142,7 @@ impl EntityDb { times_per_timeline: Default::default(), tree: crate::EntityTree::root(), data_store, - resolver: re_query_cache::PromiseResolver::default(), + resolver: re_query::PromiseResolver::default(), query_caches, stats: IngestionStatistics::new(store_id), } @@ -192,12 +192,12 @@ impl EntityDb { } #[inline] - pub fn query_caches(&self) -> &re_query_cache::Caches { + pub fn query_caches(&self) -> &re_query::Caches { &self.query_caches } #[inline] - pub fn resolver(&self) -> &re_query_cache::PromiseResolver { + pub fn resolver(&self) -> &re_query::PromiseResolver { &self.resolver } @@ -209,7 +209,7 @@ impl EntityDb { query: &re_data_store::LatestAtQuery, ) -> PromiseResult> where - re_query_cache::CachedLatestAtResults: re_query_cache::ToArchetype, + re_query::LatestAtResults: re_query::ToArchetype, { let results = self.query_caches().latest_at( self.store(), @@ -218,12 +218,12 @@ impl EntityDb { A::all_components().iter().copied(), // no generics! ); - use re_query_cache::ToArchetype as _; + use re_query::ToArchetype as _; match results.to_archetype(self.resolver()).flatten() { PromiseResult::Pending => PromiseResult::Pending, PromiseResult::Error(err) => { - if let Some(err) = err.downcast_ref::() { - if matches!(err, re_query_cache::QueryError::PrimaryNotFound(_)) { + if let Some(err) = err.downcast_ref::() { + if matches!(err, re_query::QueryError::PrimaryNotFound(_)) { return PromiseResult::Ready(None); } } @@ -240,7 +240,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { + ) -> Option> { self.query_caches().latest_at_component::( self.store(), self.resolver(), @@ -254,7 +254,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { + ) -> Option> { self.query_caches().latest_at_component_quiet::( self.store(), self.resolver(), @@ -268,7 +268,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option<(EntityPath, re_query_cache::CachedLatestAtMonoResult)> { + ) -> Option<(EntityPath, re_query::LatestAtMonoResult)> { self.query_caches() .latest_at_component_at_closest_ancestor::( self.store(), diff --git a/crates/re_entity_db/src/lib.rs b/crates/re_entity_db/src/lib.rs index e431475ea747..1d981b4a4d3f 100644 --- a/crates/re_entity_db/src/lib.rs +++ b/crates/re_entity_db/src/lib.rs @@ -34,7 +34,7 @@ pub(crate) use self::entity_tree::{ClearCascade, CompactedStoreEvents}; use re_log_types::DataTableError; pub use re_log_types::{EntityPath, EntityPathPart, TimeInt, Timeline}; -pub use re_query_cache::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +pub use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; #[cfg(feature = "serde")] pub use blueprint::components::EntityPropertiesComponent; @@ -43,7 +43,7 @@ pub use editable_auto_value::EditableAutoValue; pub mod external { pub use re_data_store; - pub use re_query_cache; + pub use re_query; } // ---------------------------------------------------------------------------- diff --git a/crates/re_query/Cargo.toml b/crates/re_query/Cargo.toml index 66c9327a5b16..9d223195d0b5 100644 --- a/crates/re_query/Cargo.toml +++ b/crates/re_query/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "re_query" authors.workspace = true -description = "Querying data in the re_data_store" +description = "High-level query APIs" edition.workspace = true homepage.workspace = true include.workspace = true @@ -20,37 +20,54 @@ all-features = true [features] -default = [] +default = ["to_archetype"] -## Enable (de)serialization using serde. -serde = ["dep:serde"] +## Implements `ToArchetype` for all builtin archetypes on `LatestAtResults`. +to_archetype = ["dep:re_types", "dep:re_types_blueprint"] + +## Enable codegen helper binaries (generates ClampedZip & RangeZip implementations). +codegen = ["unindent"] [dependencies] # Rerun dependencies: re_data_store.workspace = true +re_error.workspace = true re_format.workspace = true -re_format_arrow.workspace = true -re_log_types.workspace = true -re_types_core.workspace = true re_log.workspace = true +re_log_types.workspace = true re_tracing.workspace = true +re_tuid.workspace = true +re_types_core.workspace = true + +# Rerun dependencies (optional): +re_types = { workspace = true, optional = true } +re_types_blueprint = { workspace = true, optional = true } # External dependencies: +ahash.workspace = true +anyhow.workspace = true arrow2.workspace = true backtrace.workspace = true -document-features.workspace = true -itertools = { workspace = true } -serde = { workspace = true, features = ["derive", "rc"], optional = true } -smallvec.workspace = true +indent.workspace = true +indexmap.workspace = true +itertools.workspace = true +nohash-hasher.workspace = true +parking_lot.workspace = true +paste.workspace = true +seq-macro.workspace = true +static_assertions.workspace = true thiserror.workspace = true +web-time.workspace = true + +# External dependencies (optional): +unindent = { workspace = true, optional = true } [dev-dependencies] re_types = { workspace = true, features = ["datagen"] } criterion.workspace = true -itertools = { workspace = true } mimalloc.workspace = true rand = { workspace = true, features = ["std", "std_rng"] } similar-asserts.workspace = true @@ -60,6 +77,25 @@ similar-asserts.workspace = true bench = false +[[example]] +name = "latest_at_archetype" +required-features = ["to_archetype"] + + +[[bin]] +name = "clamped_zip" +required-features = ["codegen"] + + +[[bin]] +name = "range_zip" +required-features = ["codegen"] + + +[[bench]] +name = "flat_vec_deque" +harness = false + [[bench]] -name = "query_benchmark" +name = "latest_at" harness = false diff --git a/crates/re_query/README.md b/crates/re_query/README.md index 79097b9e5cbe..7d0c4241b353 100644 --- a/crates/re_query/README.md +++ b/crates/re_query/README.md @@ -7,4 +7,4 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) -Querying data in the `re_data_store`. +High-level query APIs. diff --git a/crates/re_query_cache/benches/flat_vec_deque.rs b/crates/re_query/benches/flat_vec_deque.rs similarity index 99% rename from crates/re_query_cache/benches/flat_vec_deque.rs rename to crates/re_query/benches/flat_vec_deque.rs index d12e10293c0e..bce849d9a43c 100644 --- a/crates/re_query_cache/benches/flat_vec_deque.rs +++ b/crates/re_query/benches/flat_vec_deque.rs @@ -2,7 +2,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use itertools::Itertools as _; -use re_query_cache::FlatVecDeque; +use re_query::FlatVecDeque; // --- diff --git a/crates/re_query_cache/benches/latest_at.rs b/crates/re_query/benches/latest_at.rs similarity index 98% rename from crates/re_query_cache/benches/latest_at.rs rename to crates/re_query/benches/latest_at.rs index 599c73726ef9..feba6dde04f6 100644 --- a/crates/re_query_cache/benches/latest_at.rs +++ b/crates/re_query/benches/latest_at.rs @@ -6,8 +6,8 @@ use criterion::{criterion_group, criterion_main, Criterion}; use itertools::Itertools; use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query2::{clamped_zip_1x1, PromiseResolver}; -use re_query_cache::{CachedLatestAtResults, Caches}; +use re_query::{clamped_zip_1x1, PromiseResolver}; +use re_query::{Caches, LatestAtResults}; use re_types::{ archetypes::Points2D, components::{Color, InstanceKey, Position2D, Text}, @@ -289,7 +289,7 @@ fn query_and_visit_points( // TODO(jleibs): Add Radius once we have support for it in field_types for entity_path in paths { - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( store, &query, entity_path, @@ -340,7 +340,7 @@ fn query_and_visit_strings( let mut strings = Vec::with_capacity(NUM_STRINGS as _); for entity_path in paths { - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( store, &query, entity_path, diff --git a/crates/re_query/benches/query_benchmark.rs b/crates/re_query/benches/query_benchmark.rs deleted file mode 100644 index aa5af0efe07c..000000000000 --- a/crates/re_query/benches/query_benchmark.rs +++ /dev/null @@ -1,313 +0,0 @@ -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - -use criterion::{criterion_group, criterion_main, Criterion}; - -use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query::query_archetype; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D, Text}, -}; -use re_types_core::Loggable as _; - -// --- - -#[cfg(not(debug_assertions))] -const NUM_FRAMES_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_FRAMES_STRINGS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_STRINGS: u32 = 1_000; - -// `cargo test` also runs the benchmark setup code, so make sure they run quickly: -#[cfg(debug_assertions)] -const NUM_FRAMES_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_FRAMES_STRINGS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_STRINGS: u32 = 1; - -criterion_group!( - benches, - mono_points, - mono_strings, - batch_points, - batch_strings -); -criterion_main!(benches); - -// --- Benchmarks --- - -pub fn build_some_point2d(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0))) - .collect() -} - -/// Create `len` dummy colors -pub fn build_some_colors(len: usize) -> Vec { - (0..len).map(|i| Color::from(i as u32)).collect() -} - -/// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`re_log_types::TimePoint`]. -pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { - (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) -} - -pub fn build_some_strings(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| { - let ilen: usize = rng.gen_range(0..10000); - let s: String = rand::thread_rng() - .sample_iter(&rand::distributions::Alphanumeric) - .take(ilen) - .map(char::from) - .collect(); - Text::from(s) - }) - .collect() -} - -fn mono_points(c: &mut Criterion) { - // Each mono point gets logged at a different path - let paths = (0..NUM_POINTS) - .map(move |point_idx| entity_path!("points", point_idx.to_string())) - .collect_vec(); - let msgs = build_points_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - // Mono-insert is slow -- decrease the sample size - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); - }); - } -} - -fn mono_strings(c: &mut Criterion) { - // Each mono string gets logged at a different path - let paths = (0..NUM_STRINGS) - .map(move |string_idx| entity_path!("strings", string_idx.to_string())) - .collect_vec(); - let msgs = build_strings_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); - }); - } -} - -fn batch_points(c: &mut Criterion) { - // Batch points are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_points_rows(&paths, NUM_POINTS as _); - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); - }); - } -} - -fn batch_strings(c: &mut Criterion) { - // Batch strings are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_strings_rows(&paths, NUM_STRINGS as _); - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); - }); - } -} - -// --- Helpers --- - -fn build_points_rows(paths: &[EntityPath], num_points: usize) -> Vec { - (0..NUM_FRAMES_POINTS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_points as _, - ( - build_some_point2d(num_points), - build_some_colors(num_points), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec { - (0..NUM_FRAMES_STRINGS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_strings as _, - // We still need to create points because they are the primary for the - // archetype query we want to do. We won't actually deserialize the points - // during the query -- we just need it for the primary keys. - // TODO(jleibs): switch this to use `TextEntry` once the new type has - // landed. - ( - build_some_point2d(num_strings), - build_some_strings(num_strings), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn insert_rows<'a>(msgs: impl Iterator) -> DataStore { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - msgs.for_each(|row| { - store.insert_row(row).unwrap(); - }); - store -} - -struct SavePoint { - _pos: Position2D, - _color: Option, -} - -fn query_and_visit_points(store: &DataStore, paths: &[EntityPath]) -> Vec { - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_POINTS as i64 / 2); - - let mut points = Vec::with_capacity(NUM_POINTS as _); - - // TODO(jleibs): Add Radius once we have support for it in field_types - for path in paths { - let arch_view = query_archetype::(store, &query, path).unwrap(); - itertools::izip!( - arch_view.iter_required_component::().unwrap(), - arch_view.iter_optional_component::().unwrap() - ) - .for_each(|(pos, color)| { - points.push(SavePoint { - _pos: pos, - _color: color, - }); - }); - } - assert_eq!(NUM_POINTS as usize, points.len()); - points -} - -struct SaveString { - _label: Option, -} - -fn query_and_visit_strings(store: &DataStore, paths: &[EntityPath]) -> Vec { - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_STRINGS as i64 / 2); - - let mut strings = Vec::with_capacity(NUM_STRINGS as _); - - for path in paths { - let arch_view = query_archetype::(store, &query, path).unwrap(); - arch_view - .iter_optional_component::() - .unwrap() - .for_each(|label| { - strings.push(SaveString { _label: label }); - }); - } - assert_eq!(NUM_STRINGS as usize, strings.len()); - - criterion::black_box(strings) -} diff --git a/crates/re_query_cache/examples/latest_at.rs b/crates/re_query/examples/latest_at.rs similarity index 89% rename from crates/re_query_cache/examples/latest_at.rs rename to crates/re_query/examples/latest_at.rs index e894e10b63a1..eb450f091cc2 100644 --- a/crates/re_query_cache/examples/latest_at.rs +++ b/crates/re_query/examples/latest_at.rs @@ -4,9 +4,8 @@ use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; use re_types_core::{Archetype as _, Loggable as _}; -use re_query_cache::{ - clamped_zip_1x2, CachedLatestAtComponentResults, CachedLatestAtResults, PromiseResolver, - PromiseResult, +use re_query::{ + clamped_zip_1x2, LatestAtComponentResults, LatestAtResults, PromiseResolver, PromiseResult, }; // --- @@ -22,13 +21,13 @@ fn main() -> anyhow::Result<()> { let query = LatestAtQuery::latest(timeline); eprintln!("query:{query:?}"); - let caches = re_query_cache::Caches::new(&store); + let caches = re_query::Caches::new(&store); // First, get the results for this query. // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( &store, &query, &entity_path.into(), @@ -41,9 +40,9 @@ fn main() -> anyhow::Result<()> { // * `get` returns an option // // At this point we still don't know whether they are cached or not. That's the next step. - let points: &CachedLatestAtComponentResults = results.get_required(MyPoint::name())?; - let colors: &CachedLatestAtComponentResults = results.get_or_empty(MyColor::name()); - let labels: &CachedLatestAtComponentResults = results.get_or_empty(MyLabel::name()); + let points: &LatestAtComponentResults = results.get_required(MyPoint::name())?; + let colors: &LatestAtComponentResults = results.get_or_empty(MyColor::name()); + let labels: &LatestAtComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. diff --git a/crates/re_query_cache/examples/latest_at_archetype.rs b/crates/re_query/examples/latest_at_archetype.rs similarity index 92% rename from crates/re_query_cache/examples/latest_at_archetype.rs rename to crates/re_query/examples/latest_at_archetype.rs index 94caab585ce2..af3215fdc3bc 100644 --- a/crates/re_query_cache/examples/latest_at_archetype.rs +++ b/crates/re_query/examples/latest_at_archetype.rs @@ -7,7 +7,7 @@ use re_types::{ }; use re_types_core::{Archetype as _, Loggable as _}; -use re_query_cache::{clamped_zip_1x2, CachedLatestAtResults, PromiseResolver, PromiseResult}; +use re_query::{clamped_zip_1x2, LatestAtResults, PromiseResolver, PromiseResult}; // --- @@ -22,13 +22,13 @@ fn main() -> anyhow::Result<()> { let query = LatestAtQuery::latest(timeline); eprintln!("query:{query:?}"); - let caches = re_query_cache::Caches::new(&store); + let caches = re_query::Caches::new(&store); // First, get the results for this query. // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( &store, &query, &entity_path.into(), @@ -37,7 +37,7 @@ fn main() -> anyhow::Result<()> { // Then make use of the `ToArchetype` helper trait in order to query, resolve, deserialize and // cache an entire archetype all at once. - use re_query_cache::ToArchetype as _; + use re_query::ToArchetype as _; let arch: Points2D = match results.to_archetype(&resolver).flatten() { PromiseResult::Pending => { diff --git a/crates/re_query_cache/examples/range.rs b/crates/re_query/examples/range.rs similarity index 91% rename from crates/re_query_cache/examples/range.rs rename to crates/re_query/examples/range.rs index e9bef34822eb..0defca92ed8a 100644 --- a/crates/re_query_cache/examples/range.rs +++ b/crates/re_query/examples/range.rs @@ -4,9 +4,9 @@ use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; use re_log_types::{build_frame_nr, DataRow, RowId, TimeRange, TimeType, Timeline}; use re_types_core::{Archetype as _, Loggable as _}; -use re_query_cache::{ - clamped_zip_1x2, range_zip_1x2, CachedRangeComponentResults, CachedRangeResults, - PromiseResolver, PromiseResult, +use re_query::{ + clamped_zip_1x2, range_zip_1x2, PromiseResolver, PromiseResult, RangeComponentResults, + RangeResults, }; // --- @@ -22,13 +22,13 @@ fn main() -> anyhow::Result<()> { let query = RangeQuery::new(timeline, TimeRange::EVERYTHING); eprintln!("query:{query:?}"); - let caches = re_query_cache::Caches::new(&store); + let caches = re_query::Caches::new(&store); // First, get the raw results for this query. // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. - let results: CachedRangeResults = caches.range( + let results: RangeResults = caches.range( &store, &query, &entity_path.into(), @@ -41,9 +41,9 @@ fn main() -> anyhow::Result<()> { // * `get` returns an option // // At this point we still don't know whether they are cached or not. That's the next step. - let all_points: &CachedRangeComponentResults = results.get_required(MyPoint::name())?; - let all_colors: &CachedRangeComponentResults = results.get_or_empty(MyColor::name()); - let all_labels: &CachedRangeComponentResults = results.get_or_empty(MyLabel::name()); + let all_points: &RangeComponentResults = results.get_required(MyPoint::name())?; + let all_colors: &RangeComponentResults = results.get_or_empty(MyColor::name()); + let all_labels: &RangeComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. diff --git a/crates/re_query/src/archetype_view.rs b/crates/re_query/src/archetype_view.rs deleted file mode 100644 index 371bd66dc705..000000000000 --- a/crates/re_query/src/archetype_view.rs +++ /dev/null @@ -1,669 +0,0 @@ -use std::{collections::BTreeMap, marker::PhantomData}; - -use arrow2::array::{Array, PrimitiveArray}; - -use re_log_types::{DataCell, DataCellRow, RowId, TimeInt}; -use re_types_core::{ - components::InstanceKey, Archetype, Component, ComponentName, DeserializationError, - DeserializationResult, Loggable, SerializationResult, -}; - -use crate::QueryError; - -/// A type-erased array of [`Component`] values and the corresponding [`InstanceKey`] keys. -/// -/// See: [`crate::get_component_with_instances`] -#[derive(Clone, Debug)] -pub struct ComponentWithInstances { - pub(crate) instance_keys: DataCell, - pub(crate) values: DataCell, -} - -impl std::fmt::Display for ComponentWithInstances { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let table = re_format_arrow::format_table( - [ - self.instance_keys.as_arrow_ref(), - self.values.as_arrow_ref(), - ], - ["InstanceKey", self.values.component_name().as_ref()], - ); - - f.write_fmt(format_args!("ComponentWithInstances:\n{table}")) - } -} - -impl ComponentWithInstances { - /// Name of the [`Component`] - #[inline] - pub fn name(&self) -> ComponentName { - self.values.component_name() - } - - /// Number of values. 1 for splats. - #[inline] - pub fn len(&self) -> usize { - self.values.num_instances() as _ - } - - #[inline] - /// Whether this [`ComponentWithInstances`] contains any data - pub fn is_empty(&self) -> bool { - self.values.is_empty() - } - - /// Returns the array of [`InstanceKey`]s. - #[inline] - pub fn instance_keys(&self) -> Vec { - re_tracing::profile_function!(); - self.instance_keys.to_native::() - } - - /// Returns the array of values as native [`Component`]s. - #[inline] - pub fn values<'a, C: Component + 'a>(&'a self) -> crate::Result>> { - if C::name() != self.name() { - return Err(QueryError::TypeMismatch { - actual: self.name(), - requested: C::name(), - }); - } - - Ok(self.values.try_to_native_opt::<'a, C>()?) - } - - /// Look up the value that corresponds to a given [`InstanceKey`] and convert to [`Component`] - pub fn lookup(&self, instance_key: &InstanceKey) -> crate::Result { - if C::name() != self.name() { - return Err(QueryError::TypeMismatch { - actual: self.name(), - requested: C::name(), - }); - } - let arr = self - .lookup_arrow(instance_key) - .map_or_else(|| Err(crate::ComponentNotFoundError(C::name())), Ok)?; - - let mut iter = C::from_arrow(arr.as_ref())?.into_iter(); - - let val = iter - .next() - .map_or_else(|| Err(crate::ComponentNotFoundError(C::name())), Ok)?; - Ok(val) - } - - /// Look up the value that corresponds to a given [`InstanceKey`] and return as an arrow [`Array`] - pub fn lookup_arrow(&self, instance_key: &InstanceKey) -> Option> { - let keys = self - .instance_keys - .as_arrow_ref() - .as_any() - .downcast_ref::>()? - .values(); - - // If the value is splatted, return the offset of the splat - let offset = if keys.len() == 1 && keys[0] == InstanceKey::SPLAT.0 { - 0 - } else { - // Otherwise binary search to find the offset of the instance - keys.binary_search(&instance_key.0).ok()? - }; - - (self.len() > offset) - .then(|| self.values.as_arrow_ref().sliced(offset, 1)) - .or_else(|| { - re_log::error_once!("found corrupt cell -- mismatched number of instances"); - None - }) - } - - /// Produce a [`ComponentWithInstances`] from native [`Component`] types - pub fn from_native<'a, C: Component + Clone + 'a>( - instance_keys: impl IntoIterator>>, - values: impl IntoIterator>>, - ) -> SerializationResult { - // Unwrap: If the data is valid for the native types, it's valid in serialized form. - let instance_keys = InstanceKey::to_arrow(instance_keys)?; - let values = C::to_arrow(values)?; - Ok(ComponentWithInstances { - instance_keys: DataCell::from_arrow(InstanceKey::name(), instance_keys), - values: DataCell::from_arrow(C::name(), values), - }) - } - - #[inline] - pub fn into_data_cell_row(self) -> DataCellRow { - let Self { - instance_keys, - values, - } = self; - DataCellRow(smallvec::smallvec![instance_keys, values]) - } -} - -/// Iterator over a single [`Component`] joined onto a primary [`Component`] -/// -/// This is equivalent to a left join between one table made up of the -/// [`InstanceKey`]s from the primary component and another table with the -/// [`InstanceKey`]s and values of the iterated [`Component`]. -/// -/// Instances have a [`InstanceKey::SPLAT`] key that will cause the value to be -/// repeated for the entirety of the join. -/// -/// For example -/// ```text -/// primary -/// +----------+ -/// | instance | -/// +----------+ -/// | key0 | -/// | key1 | -/// | Key2 | -/// -/// component -/// +----------+-------+ -/// | instance | value | -/// +----------+-------+ -/// | key0 | val0 | -/// | Key2 | val2 | -/// -/// SELECT value FROM LEFT JOIN primary.instance = component.instance; -/// -/// output -/// +-------+ -/// | value | -/// +-------+ -/// | val0 | -/// | NULL | -/// | val2 | -/// -/// ``` -pub struct ComponentJoinedIterator { - pub primary_instance_key_iter: IIter1, - pub component_instance_key_iter: IIter2, - pub component_value_iter: VIter, - pub next_component_instance_key: Option, - pub splatted_component_value: Option, -} - -impl Iterator for ComponentJoinedIterator -where - IIter1: Iterator, - IIter2: Iterator, - VIter: Iterator>, - C: Clone, -{ - type Item = Option; - - fn next(&mut self) -> Option> { - // For each value of primary_instance_iter we must find a result - if let Some(primary_key) = self.primary_instance_key_iter.next() { - loop { - match &self.next_component_instance_key { - // If we have a next component key, we either… - Some(instance_key) => { - if instance_key.is_splat() { - if self.splatted_component_value.is_none() { - self.splatted_component_value = - self.component_value_iter.next().flatten(); - } - break Some(self.splatted_component_value.clone()); - } else { - match primary_key.0.cmp(&instance_key.0) { - // Return a None if the primary_key hasn't reached it yet - std::cmp::Ordering::Less => break Some(None), - // Return the value if the keys match - std::cmp::Ordering::Equal => { - self.next_component_instance_key = - self.component_instance_key_iter.next(); - break self.component_value_iter.next(); - } - // Skip this component if the key is behind the primary key - std::cmp::Ordering::Greater => { - _ = self.component_value_iter.next(); - self.next_component_instance_key = - self.component_instance_key_iter.next(); - } - } - } - } - // Otherwise, we ran out of component elements. Just return - // None until the primary iter ends. - None => break Some(None), - }; - } - } else { - None - } - } -} - -impl ExactSizeIterator - for ComponentJoinedIterator -where - IIter1: ExactSizeIterator, - IIter2: ExactSizeIterator, - VIter: ExactSizeIterator>, - C: Clone, -{ -} - -/// A view of an [`Archetype`] at a particular point in time returned by [`crate::get_component_with_instances`]. -/// -/// The required [`Component`]s of an [`ArchetypeView`] determines the length of an entity -/// batch. When iterating over individual components, they will be implicitly joined onto -/// the required [`Component`]s using [`InstanceKey`] values. -#[derive(Clone, Debug)] -pub struct ArchetypeView { - /// The _data_ time of the most recent component in the view (not necessarily the primary!). - pub(crate) data_time: TimeInt, - - /// The [`RowId`] of the primary component in the view. - pub(crate) primary_row_id: RowId, - - pub(crate) components: BTreeMap, - - pub(crate) phantom: PhantomData, -} - -impl std::fmt::Display for ArchetypeView { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let first_required = self.required_comp(); - - let primary_table = re_format_arrow::format_table( - [ - first_required.instance_keys.as_arrow_ref(), - first_required.values.as_arrow_ref(), - ], - ["InstanceId", first_required.name().as_ref()], - ); - - f.write_fmt(format_args!("ArchetypeView:\n{primary_table}")) - } -} - -impl ArchetypeView { - #[inline] - pub fn num_instances(&self) -> usize { - self.required_comp().len() - } - - /// The _data_ time of the most recent component in the view (not necessarily the primary!). - #[inline] - pub fn data_time(&self) -> TimeInt { - self.data_time - } - - /// Returns the [`RowId`] associated with the _primary_ component that was used to drive this - /// entire query. - /// - /// Beware: when using this [`RowId`] for caching/versioning purposes, make sure the component - /// you are about to cache is in fact the primary component of the query! - /// See also . - #[inline] - pub fn primary_row_id(&self) -> RowId { - self.primary_row_id - } -} - -impl ArchetypeView { - #[inline] - fn required_comp(&self) -> &ComponentWithInstances { - // TODO(jleibs): Do all archetypes always have at least 1 required components? - let first_required = A::required_components()[0]; - &self.components[&first_required] - } - - /// Returns an iterator over [`InstanceKey`]s. - #[inline] - pub fn iter_instance_keys(&self) -> impl ExactSizeIterator { - re_tracing::profile_function!(); - // TODO(#2750): Maybe make this an intersection instead - self.required_comp().instance_keys().into_iter() - } - - /// Check if the entity has a component and its not empty - #[inline] - pub fn has_component(&self) -> bool { - let name = C::name(); - self.components.get(&name).map_or(false, |c| !c.is_empty()) - } - - /// Iterate over the values of a required multi-component. - #[inline] - pub fn iter_required_component<'a, C: Component + 'a>( - &'a self, - ) -> DeserializationResult + '_> { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(); - - debug_assert!(A::required_components() - .iter() - .any(|c| c.as_ref() == C::name())); - let component = self.components.get(&C::name()); - - if let Some(component) = component { - let component_value_iter = component - .values - .try_to_native() - .map_err(|err| DeserializationError::DataCellError(err.to_string()))? - .into_iter(); - - Ok(component_value_iter) - } else { - Err(DeserializationError::MissingComponent { - component: C::name(), - backtrace: ::backtrace::Backtrace::new_unresolved(), - }) - } - } - - /// Get a single required mono-component. - #[inline] - pub fn required_mono_component(&self) -> DeserializationResult { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(); - - let mut iter = self.iter_required_component::()?; - let value = iter - .next() - .ok_or_else(|| DeserializationError::MissingComponent { - component: C::name(), - backtrace: re_types_core::_Backtrace::new_unresolved(), - })?; - let count = 1 + iter.count(); - if count != 1 { - re_log::warn_once!("Expected a single value of {} but found {count}", C::name()); - } - Ok(value) - } - - /// Iterate over optional values as native [`Component`]s. - /// - /// Always produces an iterator that matches the length of a primary - /// component by joining on the `InstanceKey` values. - #[inline] - pub fn iter_optional_component<'a, C: Component + Clone + 'a>( - &'a self, - ) -> DeserializationResult> + '_> { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(C::name()); - - let component = self.components.get(&C::name()); - - // If the component is found and not empty, run the joining iterator on it. - // Otherwise just output nulls of the length of the primary. - // Note that this guard is specifically a precondition of the inner optimization - // for matched instance keys which will debug_assert if a zero-length component is - // referenced there. - let is_empty = component.map_or(true, |c| c.is_empty()); - if let (Some(component), false) = (component, is_empty) { - // NOTE(1): Autogenerated instance keys are interned behind datacells. - // If two or more rows in the store share the same keys, then they will share - // also the same cells. - // Therefore we can compare those cells, and early out if they match. - // - // NOTE(2): Comparing cells that point to the same backing storage is a simple pointer - // comparison; no data comparison involved. - // If the cells are not interned, this will fall back to a more costly data comparison: - // - If the data is the same, the cost of the comparison will be won back by having a - // faster iterator. - // - If the data isn't the same, the cost of the comparison will be dwarfed by the cost - // of the join anyway. - - if self.required_comp().instance_keys == component.instance_keys { - // This fast iterator is assumed to match the length of the - // primary component We shouldn't hit this since the store - // should enforce matched lengths for non-empty components, and - // the outer if-guard should keep us from reaching this in the - // case of an empty component. - // TODO(#1893): This assert and the implementation both need to - // be addressed when we allow single rows containing splats. - debug_assert_eq!( - self.required_comp().instance_keys.num_instances(), - component.values.num_instances() - ); - - // NOTE: A component instance cannot be optional in itself, and if we're on this - // path then we know for a fact that both batches can be intersected 1-to-1. - // Therefore there cannot be any null values, therefore we can go through the fast - // deserialization path. - let component_value_iter = { - C::from_arrow(component.values.as_arrow_ref())? - .into_iter() - .map(Some) - }; - - return Ok(itertools::Either::Left(itertools::Either::Left( - component_value_iter, - ))); - } - - let component_value_iter = - { C::from_arrow_opt(component.values.as_arrow_ref())?.into_iter() }; - - let primary_instance_key_iter = self.iter_instance_keys(); - let mut component_instance_key_iter = component.instance_keys().into_iter(); - - let next_component_instance_key = component_instance_key_iter.next(); - - Ok(itertools::Either::Left(itertools::Either::Right( - ComponentJoinedIterator { - primary_instance_key_iter, - component_instance_key_iter, - component_value_iter, - next_component_instance_key, - splatted_component_value: None, - }, - ))) - } else { - let primary = self.required_comp(); - let nulls = (0..primary.len()).map(|_| None); - Ok(itertools::Either::Right(nulls)) - } - } - - /// Get a single optional mono-component. - #[inline] - pub fn optional_mono_component(&self) -> DeserializationResult> { - let mut iter = self.iter_optional_component::()?; - if let Some(first_value) = iter.next() { - let count = 1 + iter.count(); - if count != 1 { - re_log::warn_once!("Expected a single value of {} but found {count}", C::name()); - } - Ok(first_value) - } else { - Ok(None) - } - } - - /// Iterate over optional values as native [`Component`]s. - /// - /// The contents of the cell are returned as-is, without joining with any other component. - #[inline] - pub fn iter_raw_optional_component<'a, C: Component + Clone + 'a>( - &'a self, - ) -> DeserializationResult + '_>> { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(C::name()); - - let component = self.components.get(&C::name()); - - if let Some(component) = component { - return Ok(Some( - C::from_arrow(component.values.as_arrow_ref())?.into_iter(), - )); - } - - Ok(None) - } - - /// Get a single optional mono-component. - #[inline] - pub fn raw_optional_mono_component(&self) -> DeserializationResult> { - if let Some(mut iter) = self.iter_raw_optional_component::()? { - if let Some(value) = iter.next() { - let count = 1 + iter.count(); - if count != 1 { - re_log::warn_once!( - "Expected a single value of {} but found {count}", - C::name() - ); - } - Ok(Some(value)) - } else { - Ok(None) - } - } else { - Ok(None) - } - } - - /// Helper function to produce an [`ArchetypeView`] from a collection of [`ComponentWithInstances`]. - #[inline] - pub fn from_components( - data_time: TimeInt, - primary_row_id: RowId, - components: impl IntoIterator, - ) -> Self { - Self { - data_time, - primary_row_id, - components: components - .into_iter() - .map(|comp| (comp.name(), comp)) - .collect(), - phantom: PhantomData, - } - } - - /// Convert an `ArchetypeView` back into a native Archetype instance - pub fn to_archetype(&self) -> crate::Result { - for component in A::required_components().iter() { - if self - .components - .get(component) - .map_or(true, |cwi| cwi.is_empty()) - { - return Err(QueryError::PrimaryNotFound(*component)); - } - } - - Ok(A::from_arrow_components( - self.components - .values() - .map(|comp| (comp.name(), comp.values.to_arrow())), - )?) - } - - /// Useful for tests. - pub fn to_data_cell_row_1< - 'a, - C1: re_types_core::Component + Clone + Into<::std::borrow::Cow<'a, C1>> + 'a, - >( - &self, - ) -> crate::Result { - let cell0 = DataCell::from_native(self.iter_instance_keys()); - let cell1 = DataCell::from_native_sparse(self.iter_optional_component::()?); - Ok(DataCellRow(smallvec::smallvec![cell0, cell1])) - } - - /// Useful for tests. - pub fn to_data_cell_row_2< - 'a, - C1: re_types_core::Component + Clone + Into<::std::borrow::Cow<'a, C1>> + 'a, - C2: re_types_core::Component + Clone + Into<::std::borrow::Cow<'a, C2>> + 'a, - >( - &self, - ) -> crate::Result { - let cell0 = DataCell::from_native(self.iter_instance_keys()); - let cell1 = DataCell::from_native_sparse(self.iter_optional_component::()?); - let cell2 = DataCell::from_native_sparse(self.iter_optional_component::()?); - Ok(DataCellRow(smallvec::smallvec![cell0, cell1, cell2])) - } -} - -#[test] -fn lookup_value() { - use re_types::components::{Color, InstanceKey, Position2D}; - - let instance_keys = InstanceKey::from_iter(0..5); - - let points = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let component = ComponentWithInstances::from_native(instance_keys, points).unwrap(); - - let missing_value = component.lookup_arrow(&InstanceKey(5)); - assert_eq!(missing_value, None); - - let value = component.lookup_arrow(&InstanceKey(2)).unwrap(); - - let expected_point = [points[2]]; - let expected_arrow = Position2D::to_arrow(expected_point).unwrap(); - - assert_eq!(expected_arrow, value); - - let instance_keys = [ - InstanceKey(17), - InstanceKey(47), - InstanceKey(48), - InstanceKey(99), - InstanceKey(472), - ]; - - let component = ComponentWithInstances::from_native(instance_keys, points).unwrap(); - - let missing_value = component.lookup_arrow(&InstanceKey(46)); - assert_eq!(missing_value, None); - - let value = component.lookup_arrow(&InstanceKey(99)).unwrap(); - - let expected_point = [points[3]]; - let expected_arrow = Position2D::to_arrow(expected_point).unwrap(); - - assert_eq!(expected_arrow, value); - - // Lookups with serialization - - let value = component.lookup::(&InstanceKey(99)).unwrap(); - assert_eq!(expected_point[0], value); - - let missing_value = component.lookup::(&InstanceKey(46)); - assert!(matches!( - missing_value.err().unwrap(), - QueryError::ComponentNotFound(_) - )); - - let missing_value = component.lookup::(&InstanceKey(99)); - assert!(matches!( - missing_value.err().unwrap(), - QueryError::TypeMismatch { .. } - )); -} - -#[test] -fn lookup_splat() { - use re_types::components::{InstanceKey, Position2D}; - let instances = [ - InstanceKey::SPLAT, // - ]; - let points = [ - Position2D::new(1.0, 2.0), // - ]; - - let component = ComponentWithInstances::from_native(instances, points).unwrap(); - - // Any instance we look up will return the slatted value - let value = component.lookup::(&InstanceKey(1)).unwrap(); - assert_eq!(points[0], value); - - let value = component.lookup::(&InstanceKey(99)).unwrap(); - assert_eq!(points[0], value); -} diff --git a/crates/re_query2/src/bin/clamped_zip.rs b/crates/re_query/src/bin/clamped_zip.rs similarity index 99% rename from crates/re_query2/src/bin/clamped_zip.rs rename to crates/re_query/src/bin/clamped_zip.rs index bb4b642f4ac7..571e9b89f27f 100644 --- a/crates/re_query2/src/bin/clamped_zip.rs +++ b/crates/re_query/src/bin/clamped_zip.rs @@ -340,7 +340,7 @@ fn main() { println!( " - // This file was generated using `cargo r -p re_query2 --all-features --bin clamped_zip`. + // This file was generated using `cargo r -p crate --all-features --bin clamped_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query2/src/bin/range_zip.rs b/crates/re_query/src/bin/range_zip.rs similarity index 99% rename from crates/re_query2/src/bin/range_zip.rs rename to crates/re_query/src/bin/range_zip.rs index f4af9aae0276..1a843dd5c215 100644 --- a/crates/re_query2/src/bin/range_zip.rs +++ b/crates/re_query/src/bin/range_zip.rs @@ -486,7 +486,7 @@ fn main() { println!( " - // This file was generated using `cargo r -p re_query2 --all-features --bin range_zip`. + // This file was generated using `cargo r -p crate --all-features --bin range_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query_cache/src/cache.rs b/crates/re_query/src/cache.rs similarity index 100% rename from crates/re_query_cache/src/cache.rs rename to crates/re_query/src/cache.rs diff --git a/crates/re_query_cache/src/cache_stats.rs b/crates/re_query/src/cache_stats.rs similarity index 100% rename from crates/re_query_cache/src/cache_stats.rs rename to crates/re_query/src/cache_stats.rs diff --git a/crates/re_query2/src/clamped_zip/.gitattributes b/crates/re_query/src/clamped_zip/.gitattributes similarity index 100% rename from crates/re_query2/src/clamped_zip/.gitattributes rename to crates/re_query/src/clamped_zip/.gitattributes diff --git a/crates/re_query2/src/clamped_zip/generated.rs b/crates/re_query/src/clamped_zip/generated.rs similarity index 99% rename from crates/re_query2/src/clamped_zip/generated.rs rename to crates/re_query/src/clamped_zip/generated.rs index 7a5c2222b40a..e682a50da861 100644 --- a/crates/re_query2/src/clamped_zip/generated.rs +++ b/crates/re_query/src/clamped_zip/generated.rs @@ -1,4 +1,4 @@ -// This file was generated using `cargo r -p re_query2 --all-features --bin clamped_zip`. +// This file was generated using `cargo r -p crate --all-features --bin clamped_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query2/src/clamped_zip/mod.rs b/crates/re_query/src/clamped_zip/mod.rs similarity index 100% rename from crates/re_query2/src/clamped_zip/mod.rs rename to crates/re_query/src/clamped_zip/mod.rs diff --git a/crates/re_query_cache/src/flat_vec_deque.rs b/crates/re_query/src/flat_vec_deque.rs similarity index 100% rename from crates/re_query_cache/src/flat_vec_deque.rs rename to crates/re_query/src/flat_vec_deque.rs diff --git a/crates/re_query_cache/src/latest_at/helpers.rs b/crates/re_query/src/latest_at/helpers.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/helpers.rs rename to crates/re_query/src/latest_at/helpers.rs index a941fe7b56bd..d850bfc660de 100644 --- a/crates/re_query_cache/src/latest_at/helpers.rs +++ b/crates/re_query/src/latest_at/helpers.rs @@ -3,11 +3,11 @@ use re_log_types::{EntityPath, RowId, TimeInt}; use re_types_core::Component; use re_types_core::{external::arrow2::array::Array, ComponentName}; -use crate::{CachedLatestAtComponentResults, Caches, PromiseResolver, PromiseResult}; +use crate::{Caches, LatestAtComponentResults, PromiseResolver, PromiseResult}; // --- -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { /// Returns the component data as a dense vector. /// /// Logs a warning and returns `None` if the component is missing or cannot be deserialized. @@ -241,12 +241,12 @@ impl CachedLatestAtComponentResults { // --- #[derive(Clone)] -pub struct CachedLatestAtMonoResult { +pub struct LatestAtMonoResult { pub index: (TimeInt, RowId), pub value: C, } -impl CachedLatestAtMonoResult { +impl LatestAtMonoResult { #[inline] pub fn data_time(&self) -> TimeInt { self.index.0 @@ -258,7 +258,7 @@ impl CachedLatestAtMonoResult { } } -impl std::ops::Deref for CachedLatestAtMonoResult { +impl std::ops::Deref for LatestAtMonoResult { type Target = C; #[inline] @@ -287,7 +287,7 @@ impl Caches { entity_path: &EntityPath, query: &LatestAtQuery, level: re_log::Level, - ) -> Option> { + ) -> Option> { re_tracing::profile_function!(); let results = self.latest_at(store, query, entity_path, [C::name()]); @@ -303,7 +303,7 @@ impl Caches { ); None } - PromiseResult::Ready(data) if data.len() == 1 => Some(CachedLatestAtMonoResult { + PromiseResult::Ready(data) if data.len() == 1 => Some(LatestAtMonoResult { index, value: data[0].clone(), }), @@ -343,7 +343,7 @@ impl Caches { resolver: &PromiseResolver, entity_path: &EntityPath, query: &LatestAtQuery, - ) -> Option> { + ) -> Option> { self.latest_at_component_with_log_level( store, resolver, @@ -368,7 +368,7 @@ impl Caches { resolver: &PromiseResolver, entity_path: &EntityPath, query: &LatestAtQuery, - ) -> Option> { + ) -> Option> { self.latest_at_component_with_log_level( store, resolver, @@ -385,7 +385,7 @@ impl Caches { resolver: &PromiseResolver, entity_path: &EntityPath, query: &LatestAtQuery, - ) -> Option<(EntityPath, CachedLatestAtMonoResult)> { + ) -> Option<(EntityPath, LatestAtMonoResult)> { re_tracing::profile_function!(); let mut cur_entity_path = Some(entity_path.clone()); diff --git a/crates/re_query/src/latest_at/mod.rs b/crates/re_query/src/latest_at/mod.rs new file mode 100644 index 000000000000..04511f831260 --- /dev/null +++ b/crates/re_query/src/latest_at/mod.rs @@ -0,0 +1,10 @@ +mod helpers; +mod query; +mod results; + +#[cfg(feature = "to_archetype")] +mod to_archetype; + +pub use self::helpers::LatestAtMonoResult; +pub use self::query::LatestAtCache; +pub use self::results::{LatestAtComponentResults, LatestAtResults}; diff --git a/crates/re_query_cache/src/latest_at/query.rs b/crates/re_query/src/latest_at/query.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/query.rs rename to crates/re_query/src/latest_at/query.rs index 825830e9a731..b4ca7cdfe059 100644 --- a/crates/re_query_cache/src/latest_at/query.rs +++ b/crates/re_query/src/latest_at/query.rs @@ -7,18 +7,17 @@ use parking_lot::RwLock; use re_data_store::{DataStore, LatestAtQuery, TimeInt}; use re_log_types::EntityPath; -use re_query2::Promise; use re_types_core::ComponentName; use re_types_core::SizeBytes; -use crate::{CacheKey, CachedLatestAtComponentResults, CachedLatestAtResults, Caches}; +use crate::{CacheKey, Caches, LatestAtComponentResults, LatestAtResults, Promise}; // --- impl Caches { /// Queries for the given `component_names` using latest-at semantics. /// - /// See [`CachedLatestAtResults`] for more information about how to handle the results. + /// See [`LatestAtResults`] for more information about how to handle the results. /// /// This is a cached API -- data will be lazily cached upon access. pub fn latest_at( @@ -27,10 +26,10 @@ impl Caches { query: &LatestAtQuery, entity_path: &EntityPath, component_names: impl IntoIterator, - ) -> CachedLatestAtResults { + ) -> LatestAtResults { re_tracing::profile_function!(entity_path.to_string()); - let mut results = CachedLatestAtResults::default(); + let mut results = LatestAtResults::default(); for component_name in component_names { let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); @@ -65,7 +64,7 @@ pub struct LatestAtCache { /// if there is any data available for the resulting _data_ time in [`Self::per_data_time`]. // // NOTE: `Arc` so we can share buckets across query time & data time. - pub per_query_time: BTreeMap>, + pub per_query_time: BTreeMap>, /// Organized by _data_ time. /// @@ -73,7 +72,7 @@ pub struct LatestAtCache { /// can result in a data time of `T`. // // NOTE: `Arc` so we can share buckets across query time & data time. - pub per_data_time: BTreeMap>, + pub per_data_time: BTreeMap>, /// These timestamps have been invalidated asynchronously. /// @@ -196,7 +195,7 @@ impl LatestAtCache { query: &LatestAtQuery, entity_path: &EntityPath, component_name: ComponentName, - ) -> Option> { + ) -> Option> { re_tracing::profile_scope!("latest_at", format!("{query:?}")); let LatestAtCache { @@ -246,7 +245,7 @@ impl LatestAtCache { return None; }; - let bucket = Arc::new(CachedLatestAtComponentResults { + let bucket = Arc::new(LatestAtComponentResults { index: (data_time, row_id), promise: Some(Promise::new(cell)), cached_dense: Default::default(), diff --git a/crates/re_query_cache/src/latest_at/results.rs b/crates/re_query/src/latest_at/results.rs similarity index 85% rename from crates/re_query_cache/src/latest_at/results.rs rename to crates/re_query/src/latest_at/results.rs index 44691217ac9d..0360a02c1a40 100644 --- a/crates/re_query_cache/src/latest_at/results.rs +++ b/crates/re_query/src/latest_at/results.rs @@ -11,14 +11,14 @@ use crate::{ // --- -/// Cached results for a latest-at query. +/// Results for a latest-at query. /// /// The data is both deserialized and resolved/converted. /// -/// Use [`CachedLatestAtResults::get`], [`CachedLatestAtResults::get_required`] and -/// [`CachedLatestAtResults::get_or_empty`] in order to access the results for each individual component. +/// Use [`LatestAtResults::get`], [`LatestAtResults::get_required`] and +/// [`LatestAtResults::get_or_empty`] in order to access the results for each individual component. #[derive(Debug)] -pub struct CachedLatestAtResults { +pub struct LatestAtResults { /// The compound index of this query result. /// /// A latest-at query is a compound operation that gathers data from many different rows. @@ -27,10 +27,10 @@ pub struct CachedLatestAtResults { pub compound_index: (TimeInt, RowId), /// Results for each individual component. - pub components: IntMap>, + pub components: IntMap>, } -impl Default for CachedLatestAtResults { +impl Default for LatestAtResults { #[inline] fn default() -> Self { Self { @@ -40,31 +40,31 @@ impl Default for CachedLatestAtResults { } } -impl CachedLatestAtResults { +impl LatestAtResults { #[inline] pub fn contains(&self, component_name: impl Into) -> bool { self.components.contains_key(&component_name.into()) } - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. #[inline] pub fn get( &self, component_name: impl Into, - ) -> Option<&CachedLatestAtComponentResults> { + ) -> Option<&LatestAtComponentResults> { self.components .get(&component_name.into()) .map(|arc| &**arc) } - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. /// /// Returns an error if the component is not present. #[inline] pub fn get_required( &self, component_name: impl Into, - ) -> crate::Result<&CachedLatestAtComponentResults> { + ) -> crate::Result<&LatestAtComponentResults> { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { Ok(component) @@ -73,32 +73,28 @@ impl CachedLatestAtResults { } } - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. /// /// Returns empty results if the component is not present. #[inline] pub fn get_or_empty( &self, component_name: impl Into, - ) -> &CachedLatestAtComponentResults { + ) -> &LatestAtComponentResults { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { component } else { - static EMPTY: CachedLatestAtComponentResults = CachedLatestAtComponentResults::empty(); + static EMPTY: LatestAtComponentResults = LatestAtComponentResults::empty(); &EMPTY } } } -impl CachedLatestAtResults { +impl LatestAtResults { #[doc(hidden)] #[inline] - pub fn add( - &mut self, - component_name: ComponentName, - cached: Arc, - ) { + pub fn add(&mut self, component_name: ComponentName, cached: Arc) { // NOTE: Since this is a compound API that actually emits multiple queries, the index of the // final result is the most recent index among all of its components, as defined by time // and row-id order. @@ -119,7 +115,7 @@ impl CachedLatestAtResults { // --- /// Lazily cached results for a particular component when using a cached latest-at query. -pub struct CachedLatestAtComponentResults { +pub struct LatestAtComponentResults { pub(crate) index: (TimeInt, RowId), // Option so we can have a constant default value for `Self`. @@ -129,7 +125,7 @@ pub struct CachedLatestAtComponentResults { pub(crate) cached_dense: OnceLock>, } -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { #[inline] pub const fn empty() -> Self { Self { @@ -170,7 +166,7 @@ impl CachedLatestAtComponentResults { } } -impl SizeBytes for CachedLatestAtComponentResults { +impl SizeBytes for LatestAtComponentResults { #[inline] fn heap_size_bytes(&self) -> u64 { let Self { @@ -187,7 +183,7 @@ impl SizeBytes for CachedLatestAtComponentResults { } } -impl std::fmt::Debug for CachedLatestAtComponentResults { +impl std::fmt::Debug for LatestAtComponentResults { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { index, @@ -204,7 +200,7 @@ impl std::fmt::Debug for CachedLatestAtComponentResults { } } -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { #[inline] pub fn index(&self) -> &(TimeInt, RowId) { &self.index @@ -257,7 +253,7 @@ impl CachedLatestAtComponentResults { } } -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { fn downcast_dense(&self, cell: &DataCell) -> crate::Result<&[C]> { // `OnceLock::get` is non-blocking -- this is a best-effort fast path in case the // data has already been computed. diff --git a/crates/re_query_cache/src/latest_at/to_archetype/.gitattributes b/crates/re_query/src/latest_at/to_archetype/.gitattributes similarity index 100% rename from crates/re_query_cache/src/latest_at/to_archetype/.gitattributes rename to crates/re_query/src/latest_at/to_archetype/.gitattributes diff --git a/crates/re_query_cache/src/latest_at/to_archetype/annotation_context.rs b/crates/re_query/src/latest_at/to_archetype/annotation_context.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/annotation_context.rs rename to crates/re_query/src/latest_at/to_archetype/annotation_context.rs index 53d7683b3ce8..8afa32ea8561 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/annotation_context.rs +++ b/crates/re_query/src/latest_at/to_archetype/annotation_context.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/arrows2d.rs b/crates/re_query/src/latest_at/to_archetype/arrows2d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/arrows2d.rs rename to crates/re_query/src/latest_at/to_archetype/arrows2d.rs index f040190bd594..5adc4153fe65 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/arrows2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/arrows2d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/arrows3d.rs b/crates/re_query/src/latest_at/to_archetype/arrows3d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/arrows3d.rs rename to crates/re_query/src/latest_at/to_archetype/arrows3d.rs index 4a2a0eb34032..fe4bd99f06c5 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/arrows3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/arrows3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/asset3d.rs b/crates/re_query/src/latest_at/to_archetype/asset3d.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/asset3d.rs rename to crates/re_query/src/latest_at/to_archetype/asset3d.rs index be8c7893f790..03931257d1ce 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/asset3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/asset3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/background.rs b/crates/re_query/src/latest_at/to_archetype/background.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/background.rs rename to crates/re_query/src/latest_at/to_archetype/background.rs index 2494ac25b0e9..319228ffb294 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/background.rs +++ b/crates/re_query/src/latest_at/to_archetype/background.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/bar_chart.rs b/crates/re_query/src/latest_at/to_archetype/bar_chart.rs similarity index 93% rename from crates/re_query_cache/src/latest_at/to_archetype/bar_chart.rs rename to crates/re_query/src/latest_at/to_archetype/bar_chart.rs index 5e291449999b..7a71bf148d3d 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/bar_chart.rs +++ b/crates/re_query/src/latest_at/to_archetype/bar_chart.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/boxes2d.rs b/crates/re_query/src/latest_at/to_archetype/boxes2d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/boxes2d.rs rename to crates/re_query/src/latest_at/to_archetype/boxes2d.rs index 84559fa17b0f..dd6aeb26070f 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/boxes2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/boxes2d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/boxes3d.rs b/crates/re_query/src/latest_at/to_archetype/boxes3d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/boxes3d.rs rename to crates/re_query/src/latest_at/to_archetype/boxes3d.rs index bc9736f831be..c0790e887012 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/boxes3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/boxes3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/clear.rs b/crates/re_query/src/latest_at/to_archetype/clear.rs similarity index 91% rename from crates/re_query_cache/src/latest_at/to_archetype/clear.rs rename to crates/re_query/src/latest_at/to_archetype/clear.rs index a71abd061fc4..6d4c8f01e4b3 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/clear.rs +++ b/crates/re_query/src/latest_at/to_archetype/clear.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/container_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/container_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/container_blueprint.rs index 2e89b1ff2d1d..d6db455e1e7f 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/container_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs @@ -5,13 +5,12 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; impl crate::ToArchetype - for CachedLatestAtResults + for LatestAtResults { #[inline] fn to_archetype( diff --git a/crates/re_query_cache/src/latest_at/to_archetype/depth_image.rs b/crates/re_query/src/latest_at/to_archetype/depth_image.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/depth_image.rs rename to crates/re_query/src/latest_at/to_archetype/depth_image.rs index b0a610bc151b..802da9f44971 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/depth_image.rs +++ b/crates/re_query/src/latest_at/to_archetype/depth_image.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/disconnected_space.rs b/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/disconnected_space.rs rename to crates/re_query/src/latest_at/to_archetype/disconnected_space.rs index 21bdfadbbc2a..e409fcd63194 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/disconnected_space.rs +++ b/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/image.rs b/crates/re_query/src/latest_at/to_archetype/image.rs similarity index 93% rename from crates/re_query_cache/src/latest_at/to_archetype/image.rs rename to crates/re_query/src/latest_at/to_archetype/image.rs index f5d8ea7d7c6f..ddf966610409 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/image.rs +++ b/crates/re_query/src/latest_at/to_archetype/image.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/line_strips2d.rs b/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/line_strips2d.rs rename to crates/re_query/src/latest_at/to_archetype/line_strips2d.rs index ab6216861a69..b51624b9ab28 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/line_strips2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/line_strips3d.rs b/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/line_strips3d.rs rename to crates/re_query/src/latest_at/to_archetype/line_strips3d.rs index 0954bf35bb5f..a11a49c0eebd 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/line_strips3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/mesh3d.rs b/crates/re_query/src/latest_at/to_archetype/mesh3d.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/mesh3d.rs rename to crates/re_query/src/latest_at/to_archetype/mesh3d.rs index 0b2462e1eb1a..04c3b330042e 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/mesh3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/mesh3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/mod.rs b/crates/re_query/src/latest_at/to_archetype/mod.rs similarity index 100% rename from crates/re_query_cache/src/latest_at/to_archetype/mod.rs rename to crates/re_query/src/latest_at/to_archetype/mod.rs diff --git a/crates/re_query_cache/src/latest_at/to_archetype/panel_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs similarity index 93% rename from crates/re_query_cache/src/latest_at/to_archetype/panel_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs index 307555ffaa4b..acf76c2788dd 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/panel_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs @@ -5,13 +5,12 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; impl crate::ToArchetype - for CachedLatestAtResults + for LatestAtResults { #[inline] fn to_archetype( diff --git a/crates/re_query_cache/src/latest_at/to_archetype/pinhole.rs b/crates/re_query/src/latest_at/to_archetype/pinhole.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/pinhole.rs rename to crates/re_query/src/latest_at/to_archetype/pinhole.rs index b192479b28d8..34419beb7435 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/pinhole.rs +++ b/crates/re_query/src/latest_at/to_archetype/pinhole.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/plot_legend.rs b/crates/re_query/src/latest_at/to_archetype/plot_legend.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/plot_legend.rs rename to crates/re_query/src/latest_at/to_archetype/plot_legend.rs index 241ec44a6840..b5d466095cc1 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/plot_legend.rs +++ b/crates/re_query/src/latest_at/to_archetype/plot_legend.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/points2d.rs b/crates/re_query/src/latest_at/to_archetype/points2d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/points2d.rs rename to crates/re_query/src/latest_at/to_archetype/points2d.rs index ba928c21f306..9fd2be9a01f1 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/points2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/points2d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/points3d.rs b/crates/re_query/src/latest_at/to_archetype/points3d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/points3d.rs rename to crates/re_query/src/latest_at/to_archetype/points3d.rs index f6802a051736..2525c7ca81bf 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/points3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/points3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/scalar.rs b/crates/re_query/src/latest_at/to_archetype/scalar.rs similarity index 91% rename from crates/re_query_cache/src/latest_at/to_archetype/scalar.rs rename to crates/re_query/src/latest_at/to_archetype/scalar.rs index b14c08327799..3f715f0bba97 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/scalar.rs +++ b/crates/re_query/src/latest_at/to_archetype/scalar.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/scalar_axis.rs b/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/scalar_axis.rs rename to crates/re_query/src/latest_at/to_archetype/scalar_axis.rs index 8a7fe1107ad0..67e59fff4a5e 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/scalar_axis.rs +++ b/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/segmentation_image.rs b/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/segmentation_image.rs rename to crates/re_query/src/latest_at/to_archetype/segmentation_image.rs index 15cf8e991355..203ca4f697b3 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/segmentation_image.rs +++ b/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/series_line.rs b/crates/re_query/src/latest_at/to_archetype/series_line.rs similarity index 93% rename from crates/re_query_cache/src/latest_at/to_archetype/series_line.rs rename to crates/re_query/src/latest_at/to_archetype/series_line.rs index eae0d8411532..88895798d555 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/series_line.rs +++ b/crates/re_query/src/latest_at/to_archetype/series_line.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/series_point.rs b/crates/re_query/src/latest_at/to_archetype/series_point.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/series_point.rs rename to crates/re_query/src/latest_at/to_archetype/series_point.rs index 4487e290958a..273aca5ac53a 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/series_point.rs +++ b/crates/re_query/src/latest_at/to_archetype/series_point.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/space_view_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/space_view_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs index 9449705381c6..f4e94c1a4c16 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/space_view_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs @@ -5,14 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype - for CachedLatestAtResults -{ +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/space_view_contents.rs b/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs similarity index 91% rename from crates/re_query_cache/src/latest_at/to_archetype/space_view_contents.rs rename to crates/re_query/src/latest_at/to_archetype/space_view_contents.rs index 3fa4e0035f65..b35439f90369 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/space_view_contents.rs +++ b/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs @@ -5,14 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype - for CachedLatestAtResults -{ +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/tensor.rs b/crates/re_query/src/latest_at/to_archetype/tensor.rs similarity index 91% rename from crates/re_query_cache/src/latest_at/to_archetype/tensor.rs rename to crates/re_query/src/latest_at/to_archetype/tensor.rs index d275be94b2b4..2b72bef07906 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/tensor.rs +++ b/crates/re_query/src/latest_at/to_archetype/tensor.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/text_document.rs b/crates/re_query/src/latest_at/to_archetype/text_document.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/text_document.rs rename to crates/re_query/src/latest_at/to_archetype/text_document.rs index 25c97086443e..9d4061fff7a9 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/text_document.rs +++ b/crates/re_query/src/latest_at/to_archetype/text_document.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/text_log.rs b/crates/re_query/src/latest_at/to_archetype/text_log.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/text_log.rs rename to crates/re_query/src/latest_at/to_archetype/text_log.rs index 90bff49a5628..4cddf9829b23 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/text_log.rs +++ b/crates/re_query/src/latest_at/to_archetype/text_log.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/transform3d.rs b/crates/re_query/src/latest_at/to_archetype/transform3d.rs similarity index 91% rename from crates/re_query_cache/src/latest_at/to_archetype/transform3d.rs rename to crates/re_query/src/latest_at/to_archetype/transform3d.rs index 05abe63d9a59..7f7a1d96a383 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/transform3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/transform3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/view_coordinates.rs b/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/view_coordinates.rs rename to crates/re_query/src/latest_at/to_archetype/view_coordinates.rs index db3ad868c8ac..2abff463bb7f 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/view_coordinates.rs +++ b/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/viewport_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/viewport_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs index 3ba2039dcc99..e5c19cca9fac 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/viewport_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs @@ -5,13 +5,12 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; impl crate::ToArchetype - for CachedLatestAtResults + for LatestAtResults { #[inline] fn to_archetype( diff --git a/crates/re_query/src/lib.rs b/crates/re_query/src/lib.rs index b888c376abec..d75b866986dd 100644 --- a/crates/re_query/src/lib.rs +++ b/crates/re_query/src/lib.rs @@ -1,20 +1,35 @@ -//! Provide query-centric access to the [`re_data_store`]. +//! Caching datastructures for `re_query`. -mod archetype_view; -mod query; +mod cache; +mod cache_stats; +mod flat_vec_deque; +mod latest_at; +mod promise; mod range; -mod util; - -pub use self::archetype_view::{ArchetypeView, ComponentWithInstances}; -pub use self::query::{get_component_with_instances, query_archetype}; -pub use self::range::{range_archetype, range_component_set}; -pub use self::util::{ - query_archetype_with_history, ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary, -}; +mod visible_history; + +pub mod clamped_zip; +pub mod range_zip; + +pub use self::cache::{CacheKey, Caches}; +pub use self::cache_stats::{CachedComponentStats, CachesStats}; +pub use self::clamped_zip::*; +pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; +pub use self::latest_at::{LatestAtComponentResults, LatestAtMonoResult, LatestAtResults}; +pub use self::promise::{Promise, PromiseId, PromiseResolver, PromiseResult}; +pub use self::range::{RangeComponentResults, RangeData, RangeResults}; +pub use self::range_zip::*; +pub use self::visible_history::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; + +pub(crate) use self::latest_at::LatestAtCache; +pub(crate) use self::range::{RangeCache, RangeComponentResultsInner}; + +pub mod external { + pub use paste; + pub use seq_macro; +} -// Used for doc-tests -#[doc(hidden)] -pub use self::query::__populate_example_store; +// --- #[derive(Debug, Clone, Copy)] pub struct ComponentNotFoundError(pub re_types_core::ComponentName); @@ -58,6 +73,47 @@ pub enum QueryError { #[error("Not implemented")] NotImplemented, + + #[error(transparent)] + Other(#[from] anyhow::Error), } pub type Result = std::result::Result; + +// --- + +/// Helper extension trait to convert query results into [`re_types_core::Archetype`]s. +pub trait ToArchetype { + /// Converts the result into an [`re_types_core::Archetype`]. + /// + /// Automatically handles all aspects of the query process: deserialization, caching, promise + /// resolution, etc. + fn to_archetype( + &self, + resolver: &crate::PromiseResolver, + ) -> crate::PromiseResult>; +} + +// --- + +use re_data_store::{LatestAtQuery, RangeQuery}; + +#[derive(Debug)] +pub enum Results { + LatestAt(LatestAtQuery, LatestAtResults), + Range(RangeQuery, RangeResults), +} + +impl From<(LatestAtQuery, LatestAtResults)> for Results { + #[inline] + fn from((query, results): (LatestAtQuery, LatestAtResults)) -> Self { + Self::LatestAt(query, results) + } +} + +impl From<(RangeQuery, RangeResults)> for Results { + #[inline] + fn from((query, results): (RangeQuery, RangeResults)) -> Self { + Self::Range(query, results) + } +} diff --git a/crates/re_query2/src/promise.rs b/crates/re_query/src/promise.rs similarity index 100% rename from crates/re_query2/src/promise.rs rename to crates/re_query/src/promise.rs diff --git a/crates/re_query/src/query.rs b/crates/re_query/src/query.rs deleted file mode 100644 index 2580ff33c31f..000000000000 --- a/crates/re_query/src/query.rs +++ /dev/null @@ -1,269 +0,0 @@ -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::{EntityPath, RowId, TimeInt}; -use re_types_core::{components::InstanceKey, Archetype, ComponentName, Loggable}; - -use crate::{ArchetypeView, ComponentWithInstances, QueryError}; - -/// Retrieves a [`ComponentWithInstances`] from the [`DataStore`]. -/// -/// Returns `None` if the component is not found. -/// -/// ``` -/// # use re_data_store::LatestAtQuery; -/// # use re_log_types::{Timeline, TimeInt, example_components::{MyColor, MyPoint}}; -/// # use re_types_core::Loggable as _; -/// # let store = re_query::__populate_example_store(); -/// -/// let ent_path = "point"; -/// let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), TimeInt::new_temporal(123)); -/// -/// let (_, _, component) = re_query::get_component_with_instances( -/// &store, -/// &query, -/// &ent_path.into(), -/// MyPoint::name(), -/// ) -/// .unwrap(); -/// -/// //println!("{component}"); -/// ``` -/// -/// Outputs: -/// ```text -/// ┌─────────────┬───────────┐ -/// │ InstanceKey ┆ MyPoint │ -/// │ --- ┆ --- │ -/// │ u64 ┆ struct[2] │ -/// ╞═════════════╪═══════════╡ -/// │ 42 ┆ {1.0,2.0} │ -/// ├╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤ -/// │ 96 ┆ {3.0,4.0} │ -/// └─────────────┴───────────┘ -/// ``` -pub fn get_component_with_instances( - store: &DataStore, - query: &LatestAtQuery, - ent_path: &EntityPath, - component: ComponentName, -) -> Option<(TimeInt, RowId, ComponentWithInstances)> { - debug_assert_eq!(store.cluster_key(), InstanceKey::name()); - - let components = [InstanceKey::name(), component]; - - let (data_time, row_id, mut cells) = - store.latest_at(query, ent_path, component, &components)?; - - Some(( - data_time, - row_id, - ComponentWithInstances { - // NOTE: The unwrap cannot fail, the cluster key's presence is guaranteed - // by the store. - instance_keys: cells[0].take().unwrap(), - values: cells[1].take()?, - }, - )) -} - -/// Retrieve an [`ArchetypeView`] from the `DataStore`, as well as the associated _data_ time of -/// its _most recent component_. -/// -/// If you expect only one instance (e.g. for mono-components like `Transform` `Tensor`] -/// and have no additional components you can use `Caches::latest_at_component` instead. -/// -/// ``` -/// # use re_data_store::LatestAtQuery; -/// # use re_log_types::{Timeline, TimeInt, example_components::{MyColor, MyPoint, MyPoints}}; -/// # use re_types_core::Component; -/// # let store = re_query::__populate_example_store(); -/// -/// let ent_path = "point"; -/// let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), TimeInt::new_temporal(123)); -/// -/// let arch_view = re_query::query_archetype::( -/// &store, -/// &query, -/// &ent_path.into(), -/// ) -/// .unwrap(); -/// -/// //println!("{arch_view:?}"); -/// ``` -/// -/// Outputs: -/// ```text -/// ┌────────────────────┬───────────────┬─────────────────┐ -/// │ InstanceKey ┆ MyPoint ┆ MyColor │ -/// │ --- ┆ --- ┆ --- │ -/// │ u64 ┆ struct[2] ┆ u32 │ -/// ╞════════════════════╪═══════════════╪═════════════════╡ -/// │ 42 ┆ {1.0,2.0} ┆ null │ -/// │ 96 ┆ {3.0,4.0} ┆ 4278190080 │ -/// └────────────────────┴───────────────┴─────────────────┘ -/// ``` -pub fn query_archetype( - store: &DataStore, - query: &LatestAtQuery, - ent_path: &EntityPath, -) -> crate::Result> { - // Profiling this can be useful, but we have many queries of very small archetypes, adding a lot of profiling overhead. - //re_tracing::profile_function!(); - - let required_components: Vec<_> = A::required_components() - .iter() - .map(|component| get_component_with_instances(store, query, ent_path, *component)) - .collect(); - - // NOTE: It's important to use `PrimaryNotFound` here. Any other error will be - // reported to the user. - // - // `query_archetype` is currently run for every archetype on every path in the view - // each path that's missing the primary is then ignored rather than being visited. - for (name, c) in itertools::izip!(A::required_components().iter(), &required_components) { - if c.is_none() { - return crate::Result::Err(QueryError::PrimaryNotFound(*name)); - } - } - - use itertools::Itertools as _; - let (data_times, row_ids, required_components): (Vec<_>, Vec<_>, Vec<_>) = - required_components.into_iter().flatten().multiunzip(); - - // NOTE: Since this is a compound API that actually emits multiple queries, the data time of the - // final result is the most recent data time among all of its components. - let mut max_data_time = data_times.iter().max().copied().unwrap_or(TimeInt::STATIC); - let row_id = row_ids.first().unwrap_or(&RowId::ZERO); - - let recommended_components = A::recommended_components(); - let optional_components = A::optional_components(); - - let other_components = recommended_components - .iter() - .chain(optional_components.iter()) - .filter_map(|component| { - get_component_with_instances(store, query, ent_path, *component).map( - |(data_time, _, component_result)| { - max_data_time = TimeInt::max(max_data_time, data_time); - component_result - }, - ) - }); - - // NOTE: Need to collect so we can compute `max_data_time`. - let cwis: Vec<_> = required_components - .into_iter() - .chain(other_components) - .collect(); - let arch_view = ArchetypeView::from_components(max_data_time, *row_id, cwis); - - Ok(arch_view) -} - -/// Helper used to create an example store we can use for querying in doctests -pub fn __populate_example_store() -> DataStore { - use re_log_types::example_components::{MyColor, MyPoint}; - use re_log_types::{build_frame_nr, DataRow}; - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let instances = vec![InstanceKey(42), InstanceKey(96)]; - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - instances.len() as _, - (&instances, &positions), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - let instances = vec![InstanceKey(96)]; - let colors = vec![MyColor::from(0xff000000)]; - - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - instances.len() as _, - (instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - store -} - -// Minimal test matching the doctest for `get_component_with_instances` -#[test] -fn simple_get_component() { - use smallvec::smallvec; - - use re_data_store::LatestAtQuery; - use re_log_types::{example_components::MyPoint, DataCellRow}; - use re_log_types::{DataCell, Timeline}; - - let store = __populate_example_store(); - - let ent_path = "point"; - let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), 123); - - let (_, _, component) = - get_component_with_instances(&store, &query, &ent_path.into(), MyPoint::name()).unwrap(); - - { - let row = component.into_data_cell_row(); - eprintln!("{row:?}"); - - let instances = vec![Some(InstanceKey(42)), Some(InstanceKey(96))]; - let positions = vec![Some(MyPoint::new(1.0, 2.0)), Some(MyPoint::new(3.0, 4.0))]; - - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - ]); - - assert_eq!(row, expected); - } -} - -// Minimal test matching the doctest for `query_entity_with_primary` -#[test] -fn simple_query_archetype() { - use re_data_store::LatestAtQuery; - use re_log_types::example_components::{MyColor, MyPoint, MyPoints}; - use re_log_types::Timeline; - - let store = __populate_example_store(); - - let ent_path = "point"; - let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), 123); - - let arch_view = query_archetype::(&store, &query, &ent_path.into()).unwrap(); - - let expected_positions = [MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = [None, Some(MyColor::from(0xff000000))]; - - let view_positions: Vec<_> = arch_view - .iter_required_component::() - .unwrap() - .collect(); - - let view_colors: Vec<_> = arch_view - .iter_optional_component::() - .unwrap() - .collect(); - - assert_eq!(expected_positions, view_positions.as_slice()); - assert_eq!(expected_colors, view_colors.as_slice()); - - eprintln!("{arch_view:?}"); -} diff --git a/crates/re_query/src/range.rs b/crates/re_query/src/range.rs deleted file mode 100644 index 2e55fca35571..000000000000 --- a/crates/re_query/src/range.rs +++ /dev/null @@ -1,170 +0,0 @@ -use itertools::Itertools as _; -use re_data_store::{DataStore, LatestAtQuery, RangeQuery}; -use re_log_types::{EntityPath, TimeInt}; -use re_types_core::{Archetype, ComponentName}; - -use crate::{get_component_with_instances, ArchetypeView, ComponentWithInstances}; - -// --- - -/// Iterates over the rows of any number of components and their respective cluster keys, all from -/// the point-of-view of the required components, returning an iterator of [`ArchetypeView`]s. -/// -/// The iterator only ever yields entity-views iff a required component has changed: a change -/// affecting only optional components will not yield an entity-view. -/// However, the changes in those secondary components will be accumulated into the next yielded -/// entity-view. -/// -/// This is a streaming-join: every yielded [`ArchetypeView`] will be the result of joining the latest -/// known state of all components, from their respective point-of-views. -/// -/// ⚠ The semantics are subtle! See `examples/range.rs` for an example of use. -pub fn range_archetype<'a, A: Archetype + 'a, const N: usize>( - store: &'a DataStore, - query: &RangeQuery, - ent_path: &'a EntityPath, -) -> impl Iterator> + 'a { - re_tracing::profile_function!(); - - // TODO(jleibs) this shim is super gross - let povs: [ComponentName; 1] = A::required_components().into_owned().try_into().unwrap(); - let components: [ComponentName; N] = A::all_components().into_owned().try_into().unwrap(); - - range_component_set::(store, query, ent_path, &povs, components) -} - -/// Iterates over the rows of any number of components and their respective cluster keys, all from -/// the point-of-view of the `povs` components, returning an iterator of [`ArchetypeView`]s. -/// -/// The iterator only ever yields entity-views iff a point-of-view component has changed: a change -/// affecting only optional components will not yield an entity-view. -/// However, the changes in those secondary components will be accumulated into the next yielded -/// entity-view. -/// -/// This is a streaming-join: every yielded [`ArchetypeView`] will be the result of joining the latest -/// known state of all components, from their respective point-of-views. -/// -/// ⚠ The semantics are subtle! See `examples/range.rs` for an example of use. -pub fn range_component_set<'a, A: Archetype + 'a, const N: usize>( - store: &'a DataStore, - query: &RangeQuery, - ent_path: &'a EntityPath, - povs: &[ComponentName], - components: [ComponentName; N], -) -> impl Iterator> + 'a { - re_tracing::profile_function!(); - - let primary: ComponentName = povs[0]; - let cluster_key = store.cluster_key(); - - // TODO(cmc): Ideally, we'd want to simply add the cluster and primary key to the `components` - // array if they are missing, yielding either `[ComponentName; N+1]` or `[ComponentName; N+2]`. - // Unfortunately this is not supported on stable at the moment, and requires - // feature(generic_const_exprs) on nightly. - // - // The alternative to these assertions (and thus putting the burden on the caller), for now, - // would be to drop the constant sizes all the way down, which would be way more painful to - // deal with. - assert!(components.contains(&cluster_key), "{components:?}"); - assert!(components.contains(&primary), "{components:?}"); - - let cluster_col = components - .iter() - .find_position(|component| **component == cluster_key) - .map(|(col, _)| col) - .unwrap(); // asserted on entry - let primary_col = components - .iter() - .find_position(|component| **component == primary) - .map(|(col, _)| col) - .unwrap(); // asserted on entry - - let mut state: Vec<_> = std::iter::repeat_with(|| None) - .take(components.len()) - .collect(); - - // NOTE: This will return none for `TimeInt::Min`, i.e. range queries that start infinitely far - // into the past don't have a latest-at state! - let query_time = TimeInt::try_from(query.range.min().as_i64().saturating_sub(1)).ok(); - - let mut cwis_latest = None; - if let Some(query_time) = query_time { - let mut cwis_latest_raw: Vec<_> = std::iter::repeat_with(|| None) - .take(components.len()) - .collect(); - - // Fetch the latest data for every single component from their respective point-of-views, - // this will allow us to build up the initial state and send an initial latest-at - // entity-view if needed. - for (i, primary) in components.iter().enumerate() { - cwis_latest_raw[i] = get_component_with_instances( - store, - &LatestAtQuery::new(query.timeline, query_time), - ent_path, - *primary, - ) - .map(|(_, row_id, cwi)| (row_id, cwi)); - } - - cwis_latest = Some(cwis_latest_raw); - } - - // send the latest-at state before anything else - cwis_latest - .into_iter() - // NOTE: `false` here means we will _not_ yield the latest-at state as an actual - // ArchetypeView! - // That is a very important detail: for overlapping range queries to be correct in a - // multi-tenant cache context, we need to make sure to inherit the latest-at state - // from T-1, while also making sure to _not_ yield the view that comes with that state. - // - // Consider e.g. what happens when one system queries for `range(10, 20)` while another - // queries for `range(9, 20)`: the data at timestamp `10` would differ because of the - // statefulness of range queries! - .map(move |cwis| (query_time.unwrap_or(TimeInt::STATIC), false, cwis)) - .chain(store.range(query, ent_path, components).map( - move |(data_time, row_id, mut cells)| { - // NOTE: The unwrap cannot fail, the cluster key's presence is guaranteed - // by the store. - let instance_keys = cells[cluster_col].take().unwrap(); - let is_primary = cells[primary_col].is_some(); - let cwis = cells - .into_iter() - .map(|cell| { - cell.map(|cell| { - ( - row_id, - ComponentWithInstances { - instance_keys: instance_keys.clone(), /* shallow */ - values: cell, - }, - ) - }) - }) - .collect::>(); - (data_time, is_primary, cwis) - }, - )) - .filter_map(move |(data_time, is_primary, cwis)| { - for (i, cwi) in cwis - .into_iter() - .enumerate() - .filter(|(_, cwi)| cwi.is_some()) - { - state[i] = cwi; - } - - // We only yield if the primary component has been updated! - is_primary.then(|| { - let (row_id, _) = state[primary_col].clone().unwrap(); // shallow - - let components: Vec<_> = state - .clone() - .into_iter() - .filter_map(|cwi| cwi.map(|(_, cwi)| cwi)) - .collect(); - - ArchetypeView::from_components(data_time, row_id, components) - }) - }) -} diff --git a/crates/re_query/src/range/mod.rs b/crates/re_query/src/range/mod.rs new file mode 100644 index 000000000000..f11e2033ff8f --- /dev/null +++ b/crates/re_query/src/range/mod.rs @@ -0,0 +1,7 @@ +mod query; +mod results; + +pub use self::query::RangeCache; +pub use self::results::{ + RangeComponentResults, RangeComponentResultsInner, RangeData, RangeResults, +}; diff --git a/crates/re_query_cache/src/range/query.rs b/crates/re_query/src/range/query.rs similarity index 96% rename from crates/re_query_cache/src/range/query.rs rename to crates/re_query/src/range/query.rs index f04664b96c25..649aa7ef8700 100644 --- a/crates/re_query_cache/src/range/query.rs +++ b/crates/re_query/src/range/query.rs @@ -8,8 +8,7 @@ use re_types_core::ComponentName; use re_types_core::SizeBytes; use crate::{ - CacheKey, CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeResults, - Caches, Promise, + CacheKey, Caches, Promise, RangeComponentResults, RangeComponentResultsInner, RangeResults, }; // --- @@ -17,7 +16,7 @@ use crate::{ impl Caches { /// Queries for the given `component_names` using range semantics. /// - /// See [`CachedRangeResults`] for more information about how to handle the results. + /// See [`RangeResults`] for more information about how to handle the results. /// /// This is a cached API -- data will be lazily cached upon access. pub fn range( @@ -26,10 +25,10 @@ impl Caches { query: &RangeQuery, entity_path: &EntityPath, component_names: impl IntoIterator, - ) -> CachedRangeResults { + ) -> RangeResults { re_tracing::profile_function!(entity_path.to_string()); - let mut results = CachedRangeResults::new(query.clone()); + let mut results = RangeResults::new(query.clone()); for component_name in component_names { let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); @@ -61,7 +60,7 @@ pub struct RangeCache { /// All temporal data, organized by _data_ time. /// /// Query time is irrelevant for range queries. - pub per_data_time: CachedRangeComponentResults, + pub per_data_time: RangeComponentResults, /// Everything greater than or equal to this timestamp has been asynchronously invalidated. /// @@ -78,7 +77,7 @@ impl RangeCache { pub fn new(cache_key: CacheKey) -> Self { Self { cache_key, - per_data_time: CachedRangeComponentResults::default(), + per_data_time: RangeComponentResults::default(), pending_invalidation: None, } } @@ -149,7 +148,7 @@ impl RangeCache { query: &RangeQuery, entity_path: &EntityPath, component_name: ComponentName, - ) -> CachedRangeComponentResults { + ) -> RangeComponentResults { re_tracing::profile_scope!("range", format!("{query:?}")); let RangeCache { @@ -232,7 +231,7 @@ impl RangeCache { // --- -impl CachedRangeComponentResultsInner { +impl RangeComponentResultsInner { /// How many _indices_ across this entire cache? #[inline] pub fn num_indices(&self) -> u64 { diff --git a/crates/re_query_cache/src/range/results.rs b/crates/re_query/src/range/results.rs similarity index 92% rename from crates/re_query_cache/src/range/results.rs rename to crates/re_query/src/range/results.rs index 5f9bc83e6255..cff3abcceabc 100644 --- a/crates/re_query_cache/src/range/results.rs +++ b/crates/re_query/src/range/results.rs @@ -13,25 +13,25 @@ use re_log_types::{RowId, TimeInt, TimeRange}; use re_types_core::{Component, ComponentName, DeserializationError, SizeBytes}; use crate::{ - CachedLatestAtComponentResults, ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, + ErasedFlatVecDeque, FlatVecDeque, LatestAtComponentResults, Promise, PromiseResolver, PromiseResult, }; // --- -/// Cached results for a range query. +/// Results for a range query. /// /// The data is both deserialized and resolved/converted. /// -/// Use [`CachedRangeResults::get`], [`CachedRangeResults::get_required`] and -/// [`CachedRangeResults::get_or_empty`] in order to access the results for each individual component. +/// Use [`RangeResults::get`], [`RangeResults::get_required`] and +/// [`RangeResults::get_or_empty`] in order to access the results for each individual component. #[derive(Debug)] -pub struct CachedRangeResults { +pub struct RangeResults { pub query: RangeQuery, - pub components: IntMap, + pub components: IntMap, } -impl CachedRangeResults { +impl RangeResults { #[inline] pub(crate) fn new(query: RangeQuery) -> Self { Self { @@ -45,23 +45,20 @@ impl CachedRangeResults { self.components.contains_key(&component_name.into()) } - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + /// Returns the [`RangeComponentResults`] for the specified [`Component`]. #[inline] - pub fn get( - &self, - component_name: impl Into, - ) -> Option<&CachedRangeComponentResults> { + pub fn get(&self, component_name: impl Into) -> Option<&RangeComponentResults> { self.components.get(&component_name.into()) } - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + /// Returns the [`RangeComponentResults`] for the specified [`Component`]. /// /// Returns an error if the component is not present. #[inline] pub fn get_required( &self, component_name: impl Into, - ) -> crate::Result<&CachedRangeComponentResults> { + ) -> crate::Result<&RangeComponentResults> { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { Ok(component) @@ -74,27 +71,24 @@ impl CachedRangeResults { } } - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + /// Returns the [`RangeComponentResults`] for the specified [`Component`]. /// /// Returns empty results if the component is not present. #[inline] - pub fn get_or_empty( - &self, - component_name: impl Into, - ) -> &CachedRangeComponentResults { + pub fn get_or_empty(&self, component_name: impl Into) -> &RangeComponentResults { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { component } else { - CachedRangeComponentResults::empty() + RangeComponentResults::empty() } } } -impl CachedRangeResults { +impl RangeResults { #[doc(hidden)] #[inline] - pub fn add(&mut self, component_name: ComponentName, cached: CachedRangeComponentResults) { + pub fn add(&mut self, component_name: ComponentName, cached: RangeComponentResults) { self.components.insert(component_name, cached); } } @@ -111,17 +105,17 @@ thread_local! { /// Lazily cached results for a particular component when using a cached range query. #[derive(Debug)] -pub struct CachedRangeComponentResults { +pub struct RangeComponentResults { /// The [`TimeRange`] of the query that was used in order to retrieve these results in the /// first place. /// /// The "original" copy in the cache just stores [`TimeRange::EMPTY`]. It's meaningless. pub(crate) time_range: TimeRange, - pub(crate) inner: Arc>, + pub(crate) inner: Arc>, } -impl CachedRangeComponentResults { +impl RangeComponentResults { /// Clones the results while making sure to stamp them with the [`TimeRange`] of the associated query. #[inline] pub(crate) fn clone_at(&self, time_range: TimeRange) -> Self { @@ -132,15 +126,15 @@ impl CachedRangeComponentResults { } } -impl CachedRangeComponentResults { +impl RangeComponentResults { #[inline] pub fn empty() -> &'static Self { - static EMPTY: OnceLock = OnceLock::new(); - EMPTY.get_or_init(CachedRangeComponentResults::default) + static EMPTY: OnceLock = OnceLock::new(); + EMPTY.get_or_init(RangeComponentResults::default) } } -impl re_types_core::SizeBytes for CachedRangeComponentResults { +impl re_types_core::SizeBytes for RangeComponentResults { #[inline] fn heap_size_bytes(&self) -> u64 { // NOTE: it's all on the heap past this point. @@ -148,18 +142,18 @@ impl re_types_core::SizeBytes for CachedRangeComponentResults { } } -impl Default for CachedRangeComponentResults { +impl Default for RangeComponentResults { #[inline] fn default() -> Self { Self { time_range: TimeRange::EMPTY, - inner: Arc::new(RwLock::new(CachedRangeComponentResultsInner::empty())), + inner: Arc::new(RwLock::new(RangeComponentResultsInner::empty())), } } } -impl std::ops::Deref for CachedRangeComponentResults { - type Target = RwLock; +impl std::ops::Deref for RangeComponentResults { + type Target = RwLock; #[inline] fn deref(&self) -> &Self::Target { @@ -208,7 +202,7 @@ impl<'a, T: 'static> std::ops::Deref for Data<'a, T> { } } -pub struct CachedRangeData<'a, T> { +pub struct RangeData<'a, T> { // NOTE: Options so we can represent an empty result without having to somehow conjure a mutex // guard out of thin air. // @@ -230,14 +224,14 @@ pub struct CachedRangeData<'a, T> { reentering: &'static std::thread::LocalKey>, } -impl<'a, C: Component> CachedRangeData<'a, C> { +impl<'a, C: Component> RangeData<'a, C> { /// Useful to abstract over latest-at and ranged results. #[inline] pub fn from_latest_at( resolver: &PromiseResolver, - results: &'a CachedLatestAtComponentResults, + results: &'a LatestAtComponentResults, ) -> Self { - let CachedLatestAtComponentResults { + let LatestAtComponentResults { index, promise: _, cached_dense, @@ -256,7 +250,7 @@ impl<'a, C: Component> CachedRangeData<'a, C> { } } -impl<'a, T> Drop for CachedRangeData<'a, T> { +impl<'a, T> Drop for RangeData<'a, T> { #[inline] fn drop(&mut self) { self.reentering @@ -264,7 +258,7 @@ impl<'a, T> Drop for CachedRangeData<'a, T> { } } -impl<'a, T: 'static> CachedRangeData<'a, T> { +impl<'a, T: 'static> RangeData<'a, T> { /// Returns the current status on both ends of the range. /// /// E.g. it is possible that the front-side of the range is still waiting for pending data while @@ -343,7 +337,7 @@ impl<'a, T: 'static> CachedRangeData<'a, T> { } } -impl CachedRangeComponentResults { +impl RangeComponentResults { /// Returns the component data as a dense vector. /// /// Returns an error if the component is missing or cannot be deserialized. @@ -351,7 +345,7 @@ impl CachedRangeComponentResults { /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of /// deserializing the data into a single one, if you don't need the extra flexibility. #[inline] - pub fn to_dense(&self, resolver: &PromiseResolver) -> CachedRangeData<'_, C> { + pub fn to_dense(&self, resolver: &PromiseResolver) -> RangeData<'_, C> { // It's tracing the deserialization of an entire range query at once -- it's fine. re_tracing::profile_function!(); @@ -361,7 +355,7 @@ impl CachedRangeComponentResults { // Manufactured empty result. if self.time_range == TimeRange::EMPTY { - return CachedRangeData { + return RangeData { indices: None, data: None, time_range: TimeRange::EMPTY, @@ -584,7 +578,7 @@ impl CachedRangeComponentResults { .unwrap() }); - CachedRangeData { + RangeData { indices: Some(Indices::Cached(indices)), data: Some(Data::Cached(data)), time_range: self.time_range, @@ -598,7 +592,7 @@ impl CachedRangeComponentResults { // --- /// Lazily cached results for a particular component when using a cached range query. -pub struct CachedRangeComponentResultsInner { +pub struct RangeComponentResultsInner { pub(crate) indices: VecDeque<(TimeInt, RowId)>, /// All the pending promises that must resolved in order to fill the missing data on the @@ -626,7 +620,7 @@ pub struct CachedRangeComponentResultsInner { pub(crate) cached_dense: Option>, } -impl SizeBytes for CachedRangeComponentResultsInner { +impl SizeBytes for RangeComponentResultsInner { #[inline] fn heap_size_bytes(&self) -> u64 { let Self { @@ -647,7 +641,7 @@ impl SizeBytes for CachedRangeComponentResultsInner { } } -impl std::fmt::Debug for CachedRangeComponentResultsInner { +impl std::fmt::Debug for RangeComponentResultsInner { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { indices, @@ -676,7 +670,7 @@ impl std::fmt::Debug for CachedRangeComponentResultsInner { } } -impl CachedRangeComponentResultsInner { +impl RangeComponentResultsInner { #[inline] pub const fn empty() -> Self { Self { diff --git a/crates/re_query2/src/range_zip/.gitattributes b/crates/re_query/src/range_zip/.gitattributes similarity index 100% rename from crates/re_query2/src/range_zip/.gitattributes rename to crates/re_query/src/range_zip/.gitattributes diff --git a/crates/re_query2/src/range_zip/generated.rs b/crates/re_query/src/range_zip/generated.rs similarity index 99% rename from crates/re_query2/src/range_zip/generated.rs rename to crates/re_query/src/range_zip/generated.rs index c916479d39f2..2b575176b198 100644 --- a/crates/re_query2/src/range_zip/generated.rs +++ b/crates/re_query/src/range_zip/generated.rs @@ -1,4 +1,4 @@ -// This file was generated using `cargo r -p re_query2 --all-features --bin range_zip`. +// This file was generated using `cargo r -p crate --all-features --bin range_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query2/src/range_zip/mod.rs b/crates/re_query/src/range_zip/mod.rs similarity index 100% rename from crates/re_query2/src/range_zip/mod.rs rename to crates/re_query/src/range_zip/mod.rs diff --git a/crates/re_query/src/util.rs b/crates/re_query/src/util.rs deleted file mode 100644 index 42831caa9bb5..000000000000 --- a/crates/re_query/src/util.rs +++ /dev/null @@ -1,143 +0,0 @@ -use re_data_store::{DataStore, LatestAtQuery, RangeQuery, TimeInt, TimeRange, Timeline}; -use re_log_types::EntityPath; -use re_types_core::Archetype; - -use crate::{query_archetype, range::range_archetype, ArchetypeView}; - -// --- - -/// One of the boundaries of the visible history. -/// -/// For [`VisibleHistoryBoundary::RelativeToTimeCursor`] and [`VisibleHistoryBoundary::Absolute`], -/// the value are either nanos or frames, depending on the type of timeline. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum VisibleHistoryBoundary { - /// Boundary is a value relative to the time cursor - RelativeToTimeCursor(i64), - - /// Boundary is an absolute value - Absolute(i64), - - /// The boundary extends to infinity. - Infinite, -} - -impl VisibleHistoryBoundary { - /// Value when the boundary is set to the current time cursor. - pub const AT_CURSOR: Self = Self::RelativeToTimeCursor(0); -} - -impl Default for VisibleHistoryBoundary { - fn default() -> Self { - Self::AT_CURSOR - } -} - -/// Visible history bounds. -#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -pub struct VisibleHistory { - /// Low time boundary. - pub from: VisibleHistoryBoundary, - - /// High time boundary. - pub to: VisibleHistoryBoundary, -} - -impl VisibleHistory { - /// Value with the visible history feature is disabled. - pub const OFF: Self = Self { - from: VisibleHistoryBoundary::AT_CURSOR, - to: VisibleHistoryBoundary::AT_CURSOR, - }; - - pub const ALL: Self = Self { - from: VisibleHistoryBoundary::Infinite, - to: VisibleHistoryBoundary::Infinite, - }; - - /// Returns the start boundary of the time range given an input cursor position. - /// - /// This is not guaranteed to be lesser than or equal to [`Self::to`]. - /// Do not use this to build a [`TimeRange`], use [`Self::time_range`]. - #[doc(hidden)] - pub fn range_start_from_cursor(&self, cursor: TimeInt) -> TimeInt { - match self.from { - VisibleHistoryBoundary::Absolute(value) => TimeInt::new_temporal(value), - VisibleHistoryBoundary::RelativeToTimeCursor(value) => { - cursor + TimeInt::new_temporal(value) - } - VisibleHistoryBoundary::Infinite => TimeInt::MIN, - } - } - - /// Returns the end boundary of the time range given an input cursor position. - /// - /// This is not guaranteed to be greater than [`Self::from`]. - /// Do not use this to build a [`TimeRange`], use [`Self::time_range`]. - #[doc(hidden)] - pub fn range_end_from_cursor(&self, cursor: TimeInt) -> TimeInt { - match self.to { - VisibleHistoryBoundary::Absolute(value) => TimeInt::new_temporal(value), - VisibleHistoryBoundary::RelativeToTimeCursor(value) => { - cursor + TimeInt::new_temporal(value) - } - VisibleHistoryBoundary::Infinite => TimeInt::MAX, - } - } - - /// Returns a _sanitized_ [`TimeRange`], i.e. guaranteed to be monotonically increasing. - pub fn time_range(&self, cursor: TimeInt) -> TimeRange { - let mut from = self.range_start_from_cursor(cursor); - let mut to = self.range_end_from_cursor(cursor); - - // TODO(#4993): visible time range UI can yield inverted ranges - if from > to { - std::mem::swap(&mut from, &mut to); - } - - TimeRange::new(from, to) - } -} - -/// When showing an entity in the history view, add this much history to it. -#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -pub struct ExtraQueryHistory { - /// Is the feature enabled? - pub enabled: bool, - - /// Visible history settings for time timelines - pub nanos: VisibleHistory, - - /// Visible history settings for frame timelines - pub sequences: VisibleHistory, -} - -// --- - -pub fn query_archetype_with_history<'a, A: Archetype + 'a, const N: usize>( - store: &'a DataStore, - timeline: &'a Timeline, - time: &'a TimeInt, - history: &ExtraQueryHistory, - ent_path: &'a EntityPath, -) -> crate::Result> + 'a> { - let visible_history = match timeline.typ() { - re_log_types::TimeType::Time => history.nanos, - re_log_types::TimeType::Sequence => history.sequences, - }; - - let time_range = visible_history.time_range(*time); - - if !history.enabled || time_range.min() == time_range.max() { - let latest_query = LatestAtQuery::new(*timeline, time_range.min()); - let latest = query_archetype::(store, &latest_query, ent_path)?; - - Ok(itertools::Either::Left(std::iter::once(latest))) - } else { - let range_query = RangeQuery::new(*timeline, time_range); - - let range = range_archetype::(store, &range_query, ent_path); - - Ok(itertools::Either::Right(range)) - } -} diff --git a/crates/re_query2/src/visible_history.rs b/crates/re_query/src/visible_history.rs similarity index 100% rename from crates/re_query2/src/visible_history.rs rename to crates/re_query/src/visible_history.rs diff --git a/crates/re_query/tests/archetype_query_tests.rs b/crates/re_query/tests/archetype_query_tests.rs deleted file mode 100644 index 6160aa593a40..000000000000 --- a/crates/re_query/tests/archetype_query_tests.rs +++ /dev/null @@ -1,336 +0,0 @@ -use smallvec::smallvec; - -use re_data_store::DataStore; -use re_log_types::{build_frame_nr, DataCell, DataCellRow, DataRow, RowId, TimePoint}; -use re_query::query_archetype; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D}, -}; -use re_types_core::Loggable as _; - -#[test] -fn simple_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬─────────────┬────────────┐ - // │ instance ┆ positions2D ┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═════════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 4278190080 │ - // └──────────┴─────────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![None, Some(Color::from_rgb(255, 0, 0))]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} - -#[test] -fn static_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance.. statically! - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - TimePoint::default(), - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬───────────┬────────────┐ - // │ instance ┆ Position2D┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═══════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 4278190080 │ - // └──────────┴───────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![None, Some(Color::from_rgb(255, 0, 0))]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - // eprintln!("{arch_view:#?}"); - // eprintln!("{expected:#?}"); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} - -#[test] -fn no_instance_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign them colors with explicit instances - let colors = vec![Color::from_rgb(255, 0, 0), Color::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, colors).unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬───────────┬────────────┐ - // │ instance ┆ Position2D┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═══════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 16711680 │ - // └──────────┴───────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(255, 0, 0)), - Some(Color::from_rgb(0, 255, 0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{df:?}"); - //eprintln!("{expected:?}"); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} - -#[test] -fn missing_column_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // - // ┌──────────┬───────────┐ - // │ instance ┆ Position2D │ - // │ --- ┆ --- │ - // │ u64 ┆ struct[2] │ - // ╞══════════╪═══════════╡ - // │ 0 ┆ {1.0,2.0} │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} │ - // └──────────┴───────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - ]); - - //eprintln!("{df:?}"); - //eprintln!("{expected:?}"); - - assert_eq!( - &arch_view.to_data_cell_row_1::().unwrap(), - &expected - ); - } -} - -#[test] -fn splatted_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign all of them a color via splat - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬───────────┬────────────┐ - // │ instance ┆ Position2D┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═══════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 4278190080 │ - // └──────────┴───────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(255, 0, 0)), - Some(Color::from_rgb(255, 0, 0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{df:?}"); - //eprintln!("{expected:?}"); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} diff --git a/crates/re_query/tests/archetype_range_tests.rs b/crates/re_query/tests/archetype_range_tests.rs deleted file mode 100644 index 29c0f56b4754..000000000000 --- a/crates/re_query/tests/archetype_range_tests.rs +++ /dev/null @@ -1,675 +0,0 @@ -use smallvec::smallvec; - -use re_data_store::{DataStore, TimeInt, TimeRange}; -use re_log_types::{build_frame_nr, DataCell, DataCellRow, DataRow, EntityPath, RowId, TimePoint}; -use re_query::range_archetype; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D}, -}; -use re_types_core::Loggable as _; - -#[test] -fn simple_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(0)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(10.0, 20.0), Position2D::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #323: - // ┌─────────────┬──────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞═════════════╪══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ null │ - // └─────────────┴──────────────┴─────────────────┘ - - { - // Frame #323 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #123: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ null │ - // └────────────────────┴───────────────┴─────────────────┘ - // - // Frame #323: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ null │ - // └────────────────────┴───────────────┴─────────────────┘ - - { - // Frame #123 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors: Vec> = vec![None, None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } -} - -#[test] -fn static_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let mut row = - DataRow::from_cells1(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - row.compute_all_size_bytes(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances.clone(), colors.clone()), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(0)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances.clone(), colors.clone()), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Insert statically too! - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(10.0, 20.0), Position2D::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - // ┌───────────┬──────────┬────────┬─────────────────┬────────────────────┬────────────────────┬────────────────────────────┐ - // │ insert_id ┆ frame_nr ┆ entity ┆ Color ┆ InstanceKey ┆ rerun.row_id ┆ Point2D │ - // ╞═══════════╪══════════╪════════╪═════════════════╪════════════════════╪════════════════════╪════════════════════════════╡ - // │ 4 ┆ null ┆ point ┆ [4278190080] ┆ [1] ┆ [{167328063302246… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ 123 ┆ point ┆ null ┆ [0, 1] ┆ [{167328063302236… ┆ [{1.0,2.0}, {3.0,4.0}] │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 3 ┆ 123 ┆ point ┆ [4278190080] ┆ [1] ┆ [{167328063302245… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 5 ┆ 223 ┆ point ┆ [4278190080] ┆ [0] ┆ [{167328063302247… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 6 ┆ 223 ┆ point ┆ [4278190080] ┆ [0] ┆ [{167328063302248… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 7 ┆ 323 ┆ point ┆ null ┆ [0, 1] ┆ [{167328063302248… ┆ [{10.0,20.0}, {30.0,40.0}] │ - // └───────────┴──────────┴────────┴─────────────────┴────────────────────┴────────────────────┴────────────────────────────┘ - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - { - // Frame #323 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - { - // Frame #123 (partially static) - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - // eprintln!("{arch_view:#?}"); - // eprintln!("{expected:#?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - - // --- Third test: `[-inf, +inf]` --- - - let query = - re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - { - // Frame #123 (partially static) - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - // eprintln!("{arch_view:#?}"); - // eprintln!("{expected:#?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } -} - -#[test] -fn simple_splatted_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with a splatted instance - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![Color::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(10.0, 20.0), Position2D::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #323: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 16711680 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ 16711680 │ - // └────────────────────┴───────────────┴─────────────────┘ - - assert_eq!(results.len(), 1); - - { - // Frame #323 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(0, 255, 0)), - Some(Color::from_rgb(0, 255, 0)), - ]; - - let df = arch_view.to_data_cell_row_2::().unwrap(); - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!(&expected, &df); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #123: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ null │ - // └────────────────────┴───────────────┴─────────────────┘ - // - // Frame #323: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 16711680 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ 16711680 │ - // └────────────────────┴───────────────┴─────────────────┘ - - { - // Frame #123 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors: Vec> = vec![None, None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(0, 255, 0)), - Some(Color::from_rgb(0, 255, 0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } -} diff --git a/crates/re_query/tests/archetype_visit_tests.rs b/crates/re_query/tests/archetype_visit_tests.rs deleted file mode 100644 index b2cb5660f992..000000000000 --- a/crates/re_query/tests/archetype_visit_tests.rs +++ /dev/null @@ -1,392 +0,0 @@ -use itertools::Itertools; -use re_log_types::{RowId, TimeInt}; -use re_query::{ArchetypeView, ComponentWithInstances}; -use re_types::archetypes::Points2D; -use re_types::components::{Color, InstanceKey, Position2D}; - -#[test] -fn basic_single_iter() { - let instance_keys = InstanceKey::from_iter(0..2); - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - ]; - - let component = ComponentWithInstances::from_native(instance_keys, positions).unwrap(); - - let results = itertools::izip!( - positions.into_iter(), - component.values::().unwrap() - ) - .collect_vec(); - assert_eq!(results.len(), 2); - results - .iter() - .for_each(|(a, b)| assert_eq!(a, b.as_ref().unwrap())); -} - -#[test] -fn directly_joined_iter() { - let instance_keys = InstanceKey::from_iter(0..3); - - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - ]; - - let colors = [ - Color::from(0), // - Color::from(1), - Color::from(2), - ]; - - let positions_comp = - ComponentWithInstances::from_native(instance_keys.clone(), positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(instance_keys, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [ - Some(Color::from(0)), - Some(Color::from(1)), - Some(Color::from(2)), - ]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn joined_iter_dense_primary() { - let point_ids = InstanceKey::from_iter(0..3); - - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - ]; - - let color_ids = [ - InstanceKey(1), // - InstanceKey(2), - ]; - - let colors = [ - Color::from(1), // - Color::from(2), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [None, Some(Color::from(1)), Some(Color::from(2))]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn joined_iter_dense_secondary() { - let point_ids = [ - InstanceKey(0), // - InstanceKey(2), - InstanceKey(4), - ]; - - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - ]; - - let color_ids = InstanceKey::from_iter(0..5); - - let colors = [ - Color::from(0), // - Color::from(1), - Color::from(2), - Color::from(3), - Color::from(4), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [ - Some(Color::from(0)), // - Some(Color::from(2)), - Some(Color::from(4)), - ]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn complex_joined_iter() { - let point_ids = vec![ - InstanceKey(0), // - InstanceKey(17), - InstanceKey(42), - InstanceKey(96), - ]; - - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - ]; - - let color_ids = vec![ - InstanceKey(17), // - InstanceKey(19), - InstanceKey(44), - InstanceKey(96), - InstanceKey(254), - ]; - - let colors = vec![ - Color::from(17), // - Color::from(19), - Color::from(44), - Color::from(96), - Color::from(254), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [ - None, - Some(Color::from(17)), // - None, - Some(Color::from(96)), - ]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn single_visit() { - let instance_keys = InstanceKey::from_iter(0..4); - let positions = [ - Position2D::new(1.0, 2.0), - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - ]; - - let positions_comp = - ComponentWithInstances::from_native(instance_keys.clone(), positions).unwrap(); - - let arch_view = - ArchetypeView::::from_components(TimeInt::STATIC, RowId::ZERO, [positions_comp]); - - let mut instance_key_out = Vec::::new(); - let mut positions_out = Vec::::new(); - - itertools::izip!( - arch_view.iter_instance_keys(), - arch_view.iter_required_component::().unwrap() - ) - .for_each(|(inst, point)| { - instance_key_out.push(inst); - positions_out.push(point); - }); - - assert_eq!(instance_key_out, instance_keys); - assert_eq!(positions.as_slice(), positions_out.as_slice()); -} - -#[test] -fn joint_visit() { - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let point_ids = InstanceKey::from_iter(0..5); - - let colors = vec![ - Color::from(0xff000000), // - Color::from(0x00ff0000), - ]; - - let color_ids = vec![ - InstanceKey(2), // - InstanceKey(4), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions.clone()).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let mut positions_out = Vec::::new(); - let mut colors_out = Vec::>::new(); - - itertools::izip!( - arch_view.iter_required_component::().unwrap(), - arch_view.iter_optional_component::().unwrap() - ) - .for_each(|(point, color)| { - positions_out.push(point); - colors_out.push(color); - }); - - let expected_colors = vec![ - None, - None, - Some(Color::from(0xff000000)), - None, - Some(Color::from(0x00ff0000)), - ]; - - assert_eq!(positions, positions_out); - assert_eq!(expected_colors, colors_out); -} - -#[test] -fn joint_visit_with_empty() { - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let shared_ids = InstanceKey::from_iter(0..5); - - let colors: Vec = vec![]; - - let positions_comp = - ComponentWithInstances::from_native(shared_ids.clone(), positions.clone()).unwrap(); - let colors_comp = ComponentWithInstances::from_native(shared_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let positions_out = arch_view - .iter_required_component::() - .unwrap() - .collect_vec(); - let colors_out = arch_view - .iter_optional_component::() - .unwrap() - .collect_vec(); - assert_eq!(positions_out.len(), colors_out.len()); - - let expected_colors = vec![None, None, None, None, None]; - - assert_eq!(positions, positions_out); - assert_eq!(expected_colors, colors_out); -} - -#[test] -fn joint_visit_with_splat() { - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let shared_ids = InstanceKey::from_iter(0..5); - - let color = Color::from(0xff000000); - let colors: Vec = vec![color]; - - let positions_comp = - ComponentWithInstances::from_native(shared_ids, positions.clone()).unwrap(); - // TODO(#1893): Replace the instance_keys with shared_ids. - let colors_comp = - ComponentWithInstances::from_native(vec![InstanceKey::SPLAT], colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let positions_out = arch_view - .iter_required_component::() - .unwrap() - .collect_vec(); - let colors_out = arch_view - .iter_optional_component::() - .unwrap() - .collect_vec(); - assert_eq!(positions_out.len(), colors_out.len()); - - let expected_colors = vec![ - Some(color), - Some(color), - Some(color), - Some(color), - Some(color), - ]; - - assert_eq!(positions, positions_out); - assert_eq!(expected_colors, colors_out); -} diff --git a/crates/re_query/tests/latest_at.rs b/crates/re_query/tests/latest_at.rs new file mode 100644 index 000000000000..b5df7aca1826 --- /dev/null +++ b/crates/re_query/tests/latest_at.rs @@ -0,0 +1,589 @@ +use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; +use re_log_types::{ + build_frame_nr, + example_components::{MyColor, MyPoint, MyPoints}, + DataRow, EntityPath, RowId, TimeInt, TimePoint, +}; +use re_query::Caches; +use re_query::PromiseResolver; +use re_types::Archetype as _; +use re_types_core::{components::InstanceKey, Loggable as _}; + +// --- + +#[test] +fn simple_query() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + let expected_compound_index = (TimeInt::new_temporal(123), row.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +#[test] +fn static_query() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + TimePoint::default(), + 1, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + let expected_compound_index = (TimeInt::new_temporal(123), row1.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +#[test] +fn invalidation() { + let entity_path = "point"; + + let test_invalidation = |query: LatestAtQuery, + present_data_timepoint: TimePoint, + past_data_timepoint: TimePoint, + future_data_timepoint: TimePoint| { + let past_timestamp = past_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + let present_timestamp = present_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let colors = vec![MyColor::from_rgb(1, 2, 3)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 1, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_compound_index = (present_timestamp, row2.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // --- Modify present --- + + // Modify the PoV component + let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_compound_index = (present_timestamp, row3.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; + let row4 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let expected_compound_index = (present_timestamp, row4.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // --- Modify past --- + + // Modify the PoV component + let points_past = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; + let row5 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + points_past.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row5); + + let expected_compound_index = (present_timestamp, row4.row_id()); + let expected_points = if past_timestamp.is_static() { + &points_past + } else { + &points + }; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors_past = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; + let row6 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint, + 2, + colors_past.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row6); + + let (expected_compound_index, expected_colors) = if past_timestamp.is_static() { + ((past_timestamp, row6.row_id()), &colors_past) + } else { + ((present_timestamp, row4.row_id()), &colors) + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // --- Modify future --- + + // Modify the PoV component + let points_future = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; + let row7 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint.clone(), + 2, + points_future.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row7); + + let (expected_compound_index, expected_points) = if past_timestamp.is_static() { + ((past_timestamp, row6.row_id()), &points_past) + } else { + ((present_timestamp, row4.row_id()), &points) + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors_future = vec![MyColor::from_rgb(16, 17, 18)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint, + 1, + colors_future, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let (expected_compound_index, expected_colors) = if past_timestamp.is_static() { + ((past_timestamp, row6.row_id()), &colors_past) + } else { + ((present_timestamp, row4.row_id()), &colors) + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + }; + + let static_ = TimePoint::default(); + let frame_122 = build_frame_nr(122); + let frame_123 = build_frame_nr(123); + let frame_124 = build_frame_nr(124); + + test_invalidation( + LatestAtQuery::new(frame_123.0, frame_123.1), + [frame_123].into(), + [frame_122].into(), + [frame_124].into(), + ); + + test_invalidation( + LatestAtQuery::new(frame_123.0, frame_123.1), + [frame_123].into(), + static_, + [frame_124].into(), + ); +} + +// Test the following scenario: +// ```py +// rr.log("points", rr.Points3D([1, 2, 3]), static=True) +// +// # Do first query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[] +// +// rr.set_time(2) +// rr.log_components("points", rr.components.MyColor(0xFF0000)) +// +// # Do second query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0xFF0000] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x0000FF)) +// +// # Do third query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x0000FF] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x00FF00)) +// +// # Do fourth query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x00FF00] +// ``` +#[test] +fn invalidation_of_future_optionals() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let static_ = TimePoint::default(); + let frame2 = [build_frame_nr(2)]; + let frame3 = [build_frame_nr(3)]; + + let query_time = [build_frame_nr(9999)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = + DataRow::from_cells1_sized(RowId::new(), entity_path, static_, 2, points.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row1.row_id()); + let expected_points = &points; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::new_temporal(2), row2.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::new_temporal(3), row3.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(0, 255, 0)]; + let row4 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::new_temporal(3), row4.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +#[test] +fn static_invalidation() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + + let query_time = [build_frame_nr(9999)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 2, + points.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row1.row_id()); + let expected_points = &points; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 1, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row2.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row3.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +// --- + +fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { + caches.on_events(&[store.insert_row(row).unwrap()]); +} + +fn query_and_compare( + caches: &Caches, + store: &DataStore, + query: &LatestAtQuery, + entity_path: &EntityPath, + expected_compound_index: (TimeInt, RowId), + expected_points: &[MyPoint], + expected_colors: &[MyColor], +) { + re_log::setup_logging(); + + let resolver = PromiseResolver::default(); + + for _ in 0..3 { + let cached = caches.latest_at( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let cached_points = cached.get_required(MyPoint::name()).unwrap(); + let cached_points = cached_points + .to_dense::(&resolver) + .flatten() + .unwrap(); + + let cached_colors = cached.get_or_empty(MyColor::name()); + let cached_colors = cached_colors + .to_dense::(&resolver) + .flatten() + .unwrap(); + + // eprintln!("{}", store.to_data_table().unwrap()); + + similar_asserts::assert_eq!(expected_compound_index, cached.compound_index); + similar_asserts::assert_eq!(expected_points, cached_points); + similar_asserts::assert_eq!(expected_colors, cached_colors); + } +} diff --git a/crates/re_query/tests/range.rs b/crates/re_query/tests/range.rs new file mode 100644 index 000000000000..615e48005d29 --- /dev/null +++ b/crates/re_query/tests/range.rs @@ -0,0 +1,852 @@ +use itertools::Itertools as _; + +use re_data_store::{DataStore, RangeQuery, StoreSubscriber as _, TimeInt, TimeRange}; +use re_log_types::{ + build_frame_nr, + example_components::{MyColor, MyPoint, MyPoints}, + DataRow, EntityPath, RowId, TimePoint, +}; +use re_query::{Caches, PromiseResolver, PromiseResult}; +use re_types::{components::InstanceKey, Archetype}; +use re_types_core::Loggable as _; + +// --- + +#[test] +fn simple_range() -> anyhow::Result<()> { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path: EntityPath = "point".into(); + + let timepoint1 = [build_frame_nr(123)]; + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1_1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 2, + points1.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row1_1); + let colors1 = vec![MyColor::from_rgb(255, 0, 0)]; + let row1_2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 1, + colors1.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row1_2); + + let timepoint2 = [build_frame_nr(223)]; + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint2, + 1, + colors2.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row2); + + let timepoint3 = [build_frame_nr(323)]; + let points3 = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint3, + 2, + points3.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row3); + + // --- First test: `(timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ( + (TimeInt::new_temporal(223), row2.row_id()), + colors2.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + // --- Second test: `[timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(123), row1_1.row_id()), + points1.as_slice(), + ), // + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ( + (TimeInt::new_temporal(123), row1_2.row_id()), + colors1.as_slice(), + ), // + ( + (TimeInt::new_temporal(223), row2.row_id()), + colors2.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + Ok(()) +} + +#[test] +fn static_range() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path: EntityPath = "point".into(); + + let timepoint1 = [build_frame_nr(123)]; + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1_1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 2, + points1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1_1); + let colors1 = vec![MyColor::from_rgb(255, 0, 0)]; + let row1_2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 1, + colors1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1_2); + // Insert statically too! + let row1_3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + TimePoint::default(), + 1, + colors1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1_3); + + let timepoint2 = [build_frame_nr(223)]; + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2_1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint2, + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2_1); + // Insert statically too! + let row2_2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + TimePoint::default(), + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2_2); + + let timepoint3 = [build_frame_nr(323)]; + // Create some Positions with implicit instances + let points3 = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint3, + 2, + points3.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + // --- First test: `(timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ((TimeInt::STATIC, row2_2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + // --- Second test: `[timepoint1, timepoint3]` --- + + // The inclusion of `timepoint1` means latest-at semantics will fall back to timeless data! + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(123), row1_1.row_id()), + points1.as_slice(), + ), // + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ((TimeInt::STATIC, row2_2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + // --- Third test: `[-inf, +inf]` --- + + let query = + re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); + + // same expectations + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); +} + +#[test] +fn invalidation() { + let entity_path = "point"; + + let test_invalidation = |query: RangeQuery, + present_data_timepoint: TimePoint, + past_data_timepoint: TimePoint, + future_data_timepoint: TimePoint| { + let past_timestamp = past_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + let present_timestamp = present_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + let future_timestamp = future_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let colors2 = vec![MyColor::from_rgb(1, 2, 3)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_points = &[ + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ]; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // --- Modify present --- + + // Modify the PoV component + let points3 = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points3.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_points = &[ + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ]; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors4 = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; + let row4 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint, + 2, + colors4.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let expected_points = &[ + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ]; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // --- Modify past --- + + // Modify the PoV component + let points5 = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; + let row5 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + points5.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row5); + + let expected_points1 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ] as &[_]; + let expected_points2 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ] as &[_]; + let expected_points = if past_data_timepoint.is_static() { + expected_points1 + } else { + expected_points2 + }; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors6 = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; + let row6 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + colors6.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row6); + + let expected_colors1 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ] as &[_]; + let expected_colors2 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ] as &[_]; + let expected_colors = if past_data_timepoint.is_static() { + expected_colors1 + } else { + expected_colors2 + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // --- Modify future --- + + // Modify the PoV component + let points7 = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; + let row7 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint.clone(), + 2, + points7.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row7); + + let expected_points1 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ] as &[_]; + let expected_points2 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ((future_timestamp, row7.row_id()), points7.as_slice()), // + ] as &[_]; + let expected_points = if past_data_timepoint.is_static() { + expected_points1 + } else { + expected_points2 + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors8 = vec![MyColor::from_rgb(16, 17, 18)]; + let row8 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint, + 1, + colors8.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row8); + + let expected_colors1 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ] as &[_]; + let expected_colors2 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ((future_timestamp, row8.row_id()), colors8.as_slice()), // + ] as &[_]; + let expected_colors = if past_data_timepoint.is_static() { + expected_colors1 + } else { + expected_colors2 + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + }; + + let timeless = TimePoint::default(); + let frame_122 = build_frame_nr(122); + let frame_123 = build_frame_nr(123); + let frame_124 = build_frame_nr(124); + + test_invalidation( + RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), + [frame_123].into(), + [frame_122].into(), + [frame_124].into(), + ); + + test_invalidation( + RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), + [frame_123].into(), + timeless, + [frame_124].into(), + ); +} + +// Test the following scenario: +// ```py +// rr.log("points", rr.Points3D([1, 2, 3]), static=True) +// +// # Do first query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[] +// +// rr.set_time(2) +// rr.log_components("points", rr.components.MyColor(0xFF0000)) +// +// # Do second query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0xFF0000] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x0000FF)) +// +// # Do third query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x0000FF] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x00FF00)) +// +// # Do fourth query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x00FF00] +// ``` +#[test] +fn invalidation_of_future_optionals() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + let frame2 = [build_frame_nr(2)]; + let frame3 = [build_frame_nr(3)]; + + let query = re_data_store::RangeQuery::new(frame2[0].0, TimeRange::EVERYTHING); + + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, points1.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let expected_points = &[ + ((TimeInt::STATIC, row1.row_id()), points1.as_slice()), // + ]; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors2.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_colors = &[ + ( + (TimeInt::new_temporal(2), row2.row_id()), + colors2.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors3 = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors3.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_colors = &[ + ( + (TimeInt::new_temporal(2), row2.row_id()), + colors2.as_slice(), + ), // + ( + (TimeInt::new_temporal(3), row3.row_id()), + colors3.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors4 = vec![MyColor::from_rgb(0, 255, 0)]; + let row4 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors4.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let expected_colors = &[ + ( + (TimeInt::new_temporal(2), row2.row_id()), + colors2.as_slice(), + ), // + ( + (TimeInt::new_temporal(3), row3.row_id()), + colors3.as_slice(), + ), // + ( + (TimeInt::new_temporal(3), row4.row_id()), + colors4.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); +} + +#[test] +fn invalidation_static() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + + let frame0 = [build_frame_nr(TimeInt::ZERO)]; + let query = re_data_store::RangeQuery::new(frame0[0].0, TimeRange::EVERYTHING); + + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 2, + points1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let expected_points = &[ + ((TimeInt::STATIC, row1.row_id()), points1.as_slice()), // + ]; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_colors = &[ + ((TimeInt::STATIC, row2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors3 = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors3.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_colors = &[ + ((TimeInt::STATIC, row3.row_id()), colors3.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); +} + +// --- + +fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { + caches.on_events(&[store.insert_row(row).unwrap()]); +} + +fn query_and_compare( + caches: &Caches, + store: &DataStore, + query: &RangeQuery, + entity_path: &EntityPath, + expected_all_points_indexed: &[((TimeInt, RowId), &[MyPoint])], + expected_all_colors_indexed: &[((TimeInt, RowId), &[MyColor])], +) { + re_log::setup_logging(); + + let resolver = PromiseResolver::default(); + + for _ in 0..3 { + let cached = caches.range( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let cached_all_points = cached + .get_required(MyPoint::name()) + .unwrap() + .to_dense::(&resolver); + assert!(matches!( + cached_all_points.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())), + )); + let cached_all_points_indexed = cached_all_points.range_indexed(); + + let cached_all_colors = cached + .get_or_empty(MyColor::name()) + .to_dense::(&resolver); + assert!(matches!( + cached_all_colors.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())), + )); + let cached_all_colors_indexed = cached_all_colors.range_indexed(); + + // eprintln!("{query:?}"); + // eprintln!("{}", store.to_data_table().unwrap()); + + similar_asserts::assert_eq!( + expected_all_points_indexed, + cached_all_points_indexed + .map(|(index, data)| (*index, data)) + .collect_vec(), + ); + + similar_asserts::assert_eq!( + expected_all_colors_indexed, + cached_all_colors_indexed + .map(|(index, data)| (*index, data)) + .collect_vec(), + ); + } +} diff --git a/crates/re_query/tests/store.rs b/crates/re_query/tests/store.rs deleted file mode 100644 index 6f6e87488211..000000000000 --- a/crates/re_query/tests/store.rs +++ /dev/null @@ -1,73 +0,0 @@ -use itertools::Itertools; - -use re_data_store::{test_row, DataStore}; -use re_log_types::EntityPath; -use re_log_types::{build_frame_nr, TimeInt, TimeType, Timeline}; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D}, - datagen::{build_some_colors, build_some_positions2d}, -}; -use re_types_core::Loggable as _; - -// --- - -// This one demonstrates a nasty edge case when stream-joining multiple iterators that happen to -// share the same exact row of data at some point (because, for that specific entry, it turns out -// that those component where inserted together). -// -// When that happens, one must be very careful to not only compare time and index row numbers, but -// also make sure that, if all else if equal, the primary iterator comes last so that it gathers as -// much state as possible! - -#[test] -fn range_join_across_single_row() { - for config in re_data_store::test_util::all_configs() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - config.clone(), - ); - range_join_across_single_row_impl(&mut store); - } -} - -fn range_join_across_single_row_impl(store: &mut DataStore) { - let ent_path = EntityPath::from("this/that"); - - let positions = build_some_positions2d(3); - let colors = build_some_colors(3); - let row = test_row!(ent_path @ [build_frame_nr(42)] => 3; [positions.clone(), colors.clone()]); - store.insert_row(&row).unwrap(); - - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = re_data_store::RangeQuery::new( - timeline_frame_nr, - re_data_store::TimeRange::new(TimeInt::MIN, TimeInt::MAX), - ); - - let mut arch_views = re_query::range_archetype::( - store, &query, &ent_path, - ); - - let arch_view = arch_views.next().unwrap(); - assert!(arch_views.next().is_none()); - - let actual_instance_keys = arch_view.iter_instance_keys().collect_vec(); - let actual_positions = arch_view - .iter_required_component::() - .unwrap() - .collect_vec(); - let actual_colors = arch_view - .iter_optional_component::() - .unwrap() - .collect_vec(); - - let expected_instance_keys = vec![InstanceKey(0), InstanceKey(1), InstanceKey(2)]; - let expected_positions = positions; - let expected_colors = colors.into_iter().map(Some).collect_vec(); - - similar_asserts::assert_eq!(expected_instance_keys, actual_instance_keys); - similar_asserts::assert_eq!(expected_positions, actual_positions); - similar_asserts::assert_eq!(expected_colors, actual_colors); -} diff --git a/crates/re_query2/Cargo.toml b/crates/re_query2/Cargo.toml deleted file mode 100644 index 6953d372cd15..000000000000 --- a/crates/re_query2/Cargo.toml +++ /dev/null @@ -1,87 +0,0 @@ -[package] -name = "re_query2" -authors.workspace = true -description = "Temporary crate meant to replace re_query" -edition.workspace = true -homepage.workspace = true -include.workspace = true -license.workspace = true -# TODO(cmc): Replace re_query with this crate. Never publish this one. -publish = false -readme = "README.md" -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[lints] -workspace = true - -[package.metadata.docs.rs] -all-features = true - - -[features] -default = [] - -## Enable (de)serialization using serde. -serde = ["dep:serde"] - -## Enable codegen helper binaries (generates ClampedZip & RangeZip implementations). -codegen = ["unindent"] - - -[dependencies] -# Rerun dependencies: -re_data_store.workspace = true -re_format.workspace = true -re_format_arrow.workspace = true -re_log_types.workspace = true -re_types_core.workspace = true -re_log.workspace = true -re_tracing.workspace = true -re_tuid.workspace = true - -# External dependencies: -ahash.workspace = true -anyhow.workspace = true -arrow2.workspace = true -backtrace.workspace = true -document-features.workspace = true -itertools = { workspace = true } -nohash-hasher.workspace = true -serde = { workspace = true, features = ["derive", "rc"], optional = true } -smallvec.workspace = true -static_assertions.workspace = true -thiserror.workspace = true - -# Optional: -unindent = { workspace = true, optional = true } - - -[dev-dependencies] -re_types = { workspace = true, features = ["datagen"] } - -criterion.workspace = true -itertools = { workspace = true } -mimalloc.workspace = true -rand = { workspace = true, features = ["std", "std_rng"] } -similar-asserts.workspace = true - - -[lib] -bench = false - - -[[bin]] -name = "clamped_zip" -required-features = ["codegen"] - - -[[bin]] -name = "range_zip" -required-features = ["codegen"] - - -[[bench]] -name = "latest_at" -harness = false diff --git a/crates/re_query2/README.md b/crates/re_query2/README.md deleted file mode 100644 index 42bcc981d336..000000000000 --- a/crates/re_query2/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# re_query2 - -Temporary crate for implementing the new data APIs. Not published. - -Will replace `re_query` when ready. diff --git a/crates/re_query2/benches/latest_at.rs b/crates/re_query2/benches/latest_at.rs deleted file mode 100644 index 28b9cf14f94e..000000000000 --- a/crates/re_query2/benches/latest_at.rs +++ /dev/null @@ -1,347 +0,0 @@ -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - -use criterion::{criterion_group, criterion_main, Criterion}; - -use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query2::{clamped_zip_1x1, LatestAtResults, PromiseResolver}; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D, Text}, - Archetype as _, -}; -use re_types_core::Loggable as _; - -// --- - -#[cfg(not(debug_assertions))] -const NUM_FRAMES_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_FRAMES_STRINGS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_STRINGS: u32 = 1_000; - -// `cargo test` also runs the benchmark setup code, so make sure they run quickly: -#[cfg(debug_assertions)] -const NUM_FRAMES_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_FRAMES_STRINGS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_STRINGS: u32 = 1; - -criterion_group!( - benches, - mono_points, - mono_strings, - batch_points, - batch_strings -); -criterion_main!(benches); - -// --- Benchmarks --- - -pub fn build_some_point2d(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0))) - .collect() -} - -/// Create `len` dummy colors -pub fn build_some_colors(len: usize) -> Vec { - (0..len).map(|i| Color::from(i as u32)).collect() -} - -/// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`re_log_types::TimePoint`]. -pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { - (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) -} - -pub fn build_some_strings(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| { - let ilen: usize = rng.gen_range(0..10000); - let s: String = rand::thread_rng() - .sample_iter(&rand::distributions::Alphanumeric) - .take(ilen) - .map(char::from) - .collect(); - Text::from(s) - }) - .collect() -} - -fn mono_points(c: &mut Criterion) { - // Each mono point gets logged at a different path - let paths = (0..NUM_POINTS) - .map(move |point_idx| entity_path!("points", point_idx.to_string())) - .collect_vec(); - let msgs = build_points_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - // Mono-insert is slow -- decrease the sample size - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); - }); - } -} - -fn mono_strings(c: &mut Criterion) { - // Each mono string gets logged at a different path - let paths = (0..NUM_STRINGS) - .map(move |string_idx| entity_path!("strings", string_idx.to_string())) - .collect_vec(); - let msgs = build_strings_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); - }); - } -} - -fn batch_points(c: &mut Criterion) { - // Batch points are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_points_rows(&paths, NUM_POINTS as _); - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); - }); - } -} - -fn batch_strings(c: &mut Criterion) { - // Batch strings are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_strings_rows(&paths, NUM_STRINGS as _); - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); - }); - } -} - -// --- Helpers --- - -fn build_points_rows(paths: &[EntityPath], num_points: usize) -> Vec { - (0..NUM_FRAMES_POINTS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_points as _, - ( - build_some_point2d(num_points), - build_some_colors(num_points), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec { - (0..NUM_FRAMES_STRINGS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_strings as _, - // We still need to create points because they are the primary for the - // archetype query we want to do. We won't actually deserialize the points - // during the query -- we just need it for the primary keys. - // TODO(jleibs): switch this to use `TextEntry` once the new type has - // landed. - ( - build_some_point2d(num_strings), - build_some_strings(num_strings), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn insert_rows<'a>(msgs: impl Iterator) -> DataStore { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - msgs.for_each(|row| { - store.insert_row(row).unwrap(); - }); - store -} - -struct SavePoint { - _pos: Position2D, - _color: Option, -} - -fn query_and_visit_points(store: &DataStore, paths: &[EntityPath]) -> Vec { - let resolver = PromiseResolver::default(); - - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_POINTS as i64 / 2); - - let mut ret = Vec::with_capacity(NUM_POINTS as _); - - // TODO(jleibs): Add Radius once we have support for it in field_types - for entity_path in paths { - let results: LatestAtResults = re_query2::latest_at( - store, - &query, - entity_path, - Points2D::all_components().iter().copied(), // no generics! - ); - - let points = results.get_required(Position2D::name()).unwrap(); - let colors = results.get_or_empty(Color::name()); - - let points = points - .iter_dense::(&resolver) - .flatten() - .unwrap(); - - let colors = colors.iter_dense::(&resolver).flatten().unwrap(); - let color_default_fn = || Color::from(0xFF00FFFF); - - for (point, color) in clamped_zip_1x1(points, colors, color_default_fn) { - ret.push(SavePoint { - _pos: point, - _color: Some(color), - }); - } - } - assert_eq!(NUM_POINTS as usize, ret.len()); - ret -} - -struct SaveString { - _label: Option, -} - -fn query_and_visit_strings(store: &DataStore, paths: &[EntityPath]) -> Vec { - let resolver = PromiseResolver::default(); - - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_STRINGS as i64 / 2); - - let mut strings = Vec::with_capacity(NUM_STRINGS as _); - - for entity_path in paths { - let results: LatestAtResults = re_query2::latest_at( - store, - &query, - entity_path, - Points2D::all_components().iter().copied(), // no generics! - ); - - let points = results.get_required(Position2D::name()).unwrap(); - let colors = results.get_or_empty(Text::name()); - - let points = points - .iter_dense::(&resolver) - .flatten() - .unwrap(); - - let labels = colors.iter_dense::(&resolver).flatten().unwrap(); - let label_default_fn = || Text(String::new().into()); - - for (_point, label) in clamped_zip_1x1(points, labels, label_default_fn) { - strings.push(SaveString { - _label: Some(label), - }); - } - } - assert_eq!(NUM_STRINGS as usize, strings.len()); - - criterion::black_box(strings) -} diff --git a/crates/re_query2/examples/latest_at.rs b/crates/re_query2/examples/latest_at.rs deleted file mode 100644 index dfc7ad286299..000000000000 --- a/crates/re_query2/examples/latest_at.rs +++ /dev/null @@ -1,128 +0,0 @@ -use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; -use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; -use re_types_core::{Archetype as _, Loggable as _}; - -use re_query2::{ - clamped_zip_1x2, LatestAtComponentResults, LatestAtResults, PromiseResolver, PromiseResult, -}; - -// --- - -fn main() -> anyhow::Result<()> { - let store = store()?; - eprintln!("store:\n{}", store.to_data_table()?); - - let resolver = PromiseResolver::default(); - - let entity_path = "points"; - let timeline = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::latest(timeline); - eprintln!("query:{query:?}"); - - // First, get the raw results for this query. - // - // Raw here means that these results are neither deserialized, nor resolved/converted. - // I.e. this corresponds to the raw `DataCell`s, straight from our datastore. - let results: LatestAtResults = re_query2::latest_at( - &store, - &query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), // no generics! - ); - - // Then, grab the raw results for each individual components. - // - // This is still raw data, but now a choice has been made regarding the nullability of the - // _component batch_ itself (that says nothing about its _instances_!). - // - // * `get_required` returns an error if the component batch is missing - // * `get_or_empty` returns an empty set of results if the component if missing - // * `get` returns an option - let points: &LatestAtComponentResults = results.get_required(MyPoint::name())?; - let colors: &LatestAtComponentResults = results.get_or_empty(MyColor::name()); - let labels: &LatestAtComponentResults = results.get_or_empty(MyLabel::name()); - - // Then comes the time to resolve/convert and deserialize the data. - // These steps have to be done together for efficiency reasons. - // - // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. - // Use `PromiseResult::flatten` to simplify it down to a single result. - // - // A choice now has to be made regarding the nullability of the _component batch's instances_. - // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably - // shouldn't be using anything but `iter_dense`. - - let points = match points.iter_dense::(&resolver).flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - return Ok(()); - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - }; - - let colors = match colors.iter_dense::(&resolver).flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - return Ok(()); - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - }; - - let labels = match labels.iter_sparse::(&resolver).flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - return Ok(()); - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - }; - - // With the data now fully resolved/converted and deserialized, the joining logic can be - // applied. - // - // In most cases this will be either a clamped zip, or no joining at all. - - let color_default_fn = || MyColor::from(0xFF00FFFF); - let label_default_fn = || None; - - let results = - clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn).collect_vec(); - - eprintln!("results:\n{results:#?}"); - - Ok(()) -} - -// --- - -fn store() -> anyhow::Result { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - re_types::components::InstanceKey::name(), - Default::default(), - ); - - let entity_path = "points"; - - { - let timepoint = [build_frame_nr(123)]; - - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; - store.insert_row(&row)?; - } - - Ok(store) -} diff --git a/crates/re_query2/examples/range.rs b/crates/re_query2/examples/range.rs deleted file mode 100644 index e8c1a5227dc8..000000000000 --- a/crates/re_query2/examples/range.rs +++ /dev/null @@ -1,168 +0,0 @@ -use itertools::{izip, Itertools}; -use re_data_store::{DataStore, RangeQuery}; -use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; -use re_log_types::{build_frame_nr, DataRow, RowId, TimeRange, TimeType, Timeline}; -use re_types_core::{Archetype as _, Loggable as _}; - -use re_query2::{ - clamped_zip_1x2, range_zip_1x2, PromiseResolver, PromiseResult, RangeComponentResults, - RangeResults, -}; - -// --- - -fn main() -> anyhow::Result<()> { - let store = store()?; - eprintln!("store:\n{}", store.to_data_table()?); - - let resolver = PromiseResolver::default(); - - let entity_path = "points"; - let timeline = Timeline::new("frame_nr", TimeType::Sequence); - let query = RangeQuery::new(timeline, TimeRange::EVERYTHING); - eprintln!("query:{query:?}"); - - // First, get the raw results for this query. - // - // Raw here means that these results are neither deserialized, nor resolved/converted. - // I.e. this corresponds to the raw `DataCell`s, straight from our datastore. - let results: RangeResults = re_query2::range( - &store, - &query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), // no generics! - ); - - // Then, grab the raw results for each individual components. - // - // This is still raw data, but now a choice has been made regarding the nullability of the - // _component batch_ itself (that says nothing about its _instances_!). - // - // * `get_required` returns an error if the component batch is missing - // * `get_or_empty` returns an empty set of results if the component if missing - // * `get` returns an option - let all_points: &RangeComponentResults = results.get_required(MyPoint::name())?; - let all_colors: &RangeComponentResults = results.get_or_empty(MyColor::name()); - let all_labels: &RangeComponentResults = results.get_or_empty(MyLabel::name()); - - let all_indexed_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_indexed_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - let all_indexed_labels = izip!( - all_labels.iter_indices(), - all_labels.iter_sparse::(&resolver) - ); - - let all_frames = range_zip_1x2(all_indexed_points, all_indexed_colors, all_indexed_labels); - - // Then comes the time to resolve/convert and deserialize the data, _for each timestamp_. - // These steps have to be done together for efficiency reasons. - // - // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. - // Use `PromiseResult::flatten` to simplify it down to a single result. - // - // A choice now has to be made regarding the nullability of the _component batch's instances_. - // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably - // shouldn't be using anything but `iter_dense`. - eprintln!("results:"); - for ((data_time, row_id), points, colors, labels) in all_frames { - let points = match points.flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - continue; - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - }; - - let colors = if let Some(colors) = colors { - match colors.flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - continue; - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - } - } else { - vec![] - }; - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let labels = if let Some(labels) = labels { - match labels.flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - continue; - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - } - } else { - vec![] - }; - let label_default_fn = || None; - - // With the data now fully resolved/converted and deserialized, the joining logic can be - // applied. - // - // In most cases this will be either a clamped zip, or no joining at all. - - let results = clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn) - .collect_vec(); - eprintln!("{data_time:?} @ {row_id}:\n {results:?}"); - } - - Ok(()) -} - -// --- - -fn store() -> anyhow::Result { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - re_types::components::InstanceKey::name(), - Default::default(), - ); - - let entity_path = "points"; - - { - let timepoint = [build_frame_nr(123)]; - - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; - store.insert_row(&row)?; - } - - { - let timepoint = [build_frame_nr(456)]; - - let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let points = vec![ - MyPoint::new(10.0, 20.0), - MyPoint::new(30.0, 40.0), - MyPoint::new(50.0, 60.0), - ]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - } - - Ok(store) -} diff --git a/crates/re_query2/src/latest_at/mod.rs b/crates/re_query2/src/latest_at/mod.rs deleted file mode 100644 index dd86e3d68e3c..000000000000 --- a/crates/re_query2/src/latest_at/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod query; -mod results; - -pub use self::query::latest_at; -pub use self::results::{LatestAtComponentResults, LatestAtResults}; diff --git a/crates/re_query2/src/latest_at/query.rs b/crates/re_query2/src/latest_at/query.rs deleted file mode 100644 index a9da12168890..000000000000 --- a/crates/re_query2/src/latest_at/query.rs +++ /dev/null @@ -1,40 +0,0 @@ -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::EntityPath; -use re_types_core::ComponentName; - -use crate::LatestAtResults; - -// --- - -/// Queries for the given `component_names` using latest-at semantics. -/// -/// See [`LatestAtResults`] for more information about how to handle the results. -pub fn latest_at( - store: &DataStore, - query: &LatestAtQuery, - entity_path: &EntityPath, - component_names: impl IntoIterator, -) -> LatestAtResults { - re_tracing::profile_function!(entity_path.to_string()); - - let mut results = LatestAtResults::default(); - - for component_name in component_names { - let Some((time, row_id, mut cells)) = - store.latest_at(query, entity_path, component_name, &[component_name]) - else { - continue; - }; - - // Soundness: - // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` - // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null - if let Some(cell) = cells[0].take() { - results.add(component_name, (time, row_id), cell); - } else { - debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); - } - } - - results -} diff --git a/crates/re_query2/src/latest_at/results.rs b/crates/re_query2/src/latest_at/results.rs deleted file mode 100644 index aef7167423dc..000000000000 --- a/crates/re_query2/src/latest_at/results.rs +++ /dev/null @@ -1,224 +0,0 @@ -use nohash_hasher::IntMap; -use re_log_types::{DataCell, RowId, TimeInt}; -use re_types_core::ComponentName; -use re_types_core::{Component, DeserializationError, DeserializationResult}; - -use crate::{Promise, PromiseResolver, PromiseResult}; - -// --- - -/// Raw results for a latest-at query. -/// -/// The data is neither deserialized, nor resolved/converted. -/// It it the raw [`DataCell`]s, straight from our datastore. -/// -/// Use [`LatestAtResults::get`], [`LatestAtResults::get_required`] and [`LatestAtResults::get_or_empty`] -/// in order to access the raw results for each individual component. -#[derive(Debug, Clone)] -pub struct LatestAtResults { - /// The compound index of this query result. - /// - /// A latest-at query is a compound operation that gathers data from many different rows. - /// The index of that compound result corresponds to the index of most the recent row in all the - /// sub-results, as defined by time and row-id order. - pub compound_index: (TimeInt, RowId), - - /// Raw results for each individual component. - pub components: IntMap, -} - -impl Default for LatestAtResults { - #[inline] - fn default() -> Self { - Self { - compound_index: (TimeInt::STATIC, RowId::ZERO), - components: Default::default(), - } - } -} - -impl LatestAtResults { - #[inline] - pub fn contains(&self, component_name: impl Into) -> bool { - self.components.contains_key(&component_name.into()) - } - - /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. - #[inline] - pub fn get( - &self, - component_name: impl Into, - ) -> Option<&LatestAtComponentResults> { - self.components.get(&component_name.into()) - } - - /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. - /// - /// Returns an error if the component is not present. - #[inline] - pub fn get_required( - &self, - component_name: impl Into, - ) -> crate::Result<&LatestAtComponentResults> { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - Ok(component) - } else { - Err(DeserializationError::MissingComponent { - component: component_name, - backtrace: ::backtrace::Backtrace::new_unresolved(), - } - .into()) - } - } - - /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. - /// - /// Returns empty results if the component is not present. - #[inline] - pub fn get_or_empty( - &self, - component_name: impl Into, - ) -> &LatestAtComponentResults { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - component - } else { - static DEFAULT: LatestAtComponentResults = LatestAtComponentResults::EMPTY; - &DEFAULT - } - } -} - -impl LatestAtResults { - #[doc(hidden)] - #[inline] - pub fn add(&mut self, component_name: ComponentName, index: (TimeInt, RowId), cell: DataCell) { - // NOTE: Since this is a compound API that actually emits multiple queries, the index of the - // final result is the most recent index among all of its components, as defined by time - // and row-id order. - // - // TODO(#5303): We have to ignore the cluster key in this piece of logic for backwards compatibility - // reasons with the legacy instance-key model. This will go away next. - use re_types_core::Loggable as _; - if component_name != re_types_core::components::InstanceKey::name() - && index > self.compound_index - { - self.compound_index = index; - } - - self.components.insert( - component_name, - LatestAtComponentResults { - index, - promise: Some(Promise::new(cell)), - }, - ); - } -} - -// --- - -/// Uncached results for a particular component when using a latest-at query. -#[derive(Debug, Clone)] -pub struct LatestAtComponentResults { - index: (TimeInt, RowId), - - // Option so we can have a constant default value for `Self` for the optional+empty case. - promise: Option, -} - -impl Default for LatestAtComponentResults { - #[inline] - fn default() -> Self { - Self::EMPTY - } -} - -impl LatestAtComponentResults { - const EMPTY: Self = Self { - index: (TimeInt::STATIC, RowId::ZERO), - promise: None, - }; -} - -impl LatestAtComponentResults { - #[inline] - pub fn index(&self) -> &(TimeInt, RowId) { - &self.index - } - - /// Returns the component data as a dense vector. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_dense( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>> { - if let Some(cell) = self.promise.as_ref() { - resolver.resolve(cell).map(|cell| { - cell.try_to_native() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) - } else { - // Manufactured empty result. - PromiseResult::Ready(Ok(vec![])) - } - } - - /// Iterates over the component data, assuming it is dense. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn iter_dense( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>> { - self.to_dense(resolver) - .map(|data| data.map(|data| data.into_iter())) - } - - /// Returns the component data as a sparse vector. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_sparse( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>>> { - if let Some(cell) = self.promise.as_ref() { - resolver.resolve(cell).map(|cell| { - cell.try_to_native_opt() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) - } else { - // Manufactured empty result. - PromiseResult::Ready(Ok(vec![])) - } - } - - /// Iterates over the component data, assuming it is sparse. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn iter_sparse( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>>> { - self.to_sparse(resolver) - .map(|data| data.map(|data| data.into_iter())) - } -} diff --git a/crates/re_query2/src/lib.rs b/crates/re_query2/src/lib.rs deleted file mode 100644 index 94e94a06f803..000000000000 --- a/crates/re_query2/src/lib.rs +++ /dev/null @@ -1,81 +0,0 @@ -//! Provide query-centric access to the [`re_data_store`]. - -mod latest_at; -mod promise; -mod range; -mod visible_history; - -pub mod clamped_zip; -pub mod range_zip; - -pub use self::clamped_zip::*; -pub use self::latest_at::{latest_at, LatestAtComponentResults, LatestAtResults}; -pub use self::promise::{Promise, PromiseId, PromiseResolver, PromiseResult}; -pub use self::range::{range, RangeComponentResults, RangeResults}; -pub use self::range_zip::*; -pub use self::visible_history::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; - -// --- - -#[derive(Debug, Clone, Copy)] -pub struct ComponentNotFoundError(pub re_types_core::ComponentName); - -impl std::fmt::Display for ComponentNotFoundError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!("Could not find component: {}", self.0)) - } -} - -impl std::error::Error for ComponentNotFoundError {} - -#[derive(thiserror::Error, Debug)] -pub enum QueryError { - #[error("Tried to access a column that doesn't exist")] - BadAccess, - - #[error("Could not find primary component: {0}")] - PrimaryNotFound(re_types_core::ComponentName), - - #[error(transparent)] - ComponentNotFound(#[from] ComponentNotFoundError), - - #[error("Tried to access component of type '{actual:?}' using component '{requested:?}'")] - TypeMismatch { - actual: re_types_core::ComponentName, - requested: re_types_core::ComponentName, - }, - - #[error("Error with one or more the underlying data cells: {0}")] - DataCell(#[from] re_log_types::DataCellError), - - #[error("Error deserializing: {0}")] - DeserializationError(#[from] re_types_core::DeserializationError), - - #[error("Error serializing: {0}")] - SerializationError(#[from] re_types_core::SerializationError), - - #[error("Error converting arrow data: {0}")] - ArrowError(#[from] arrow2::error::Error), - - #[error("Not implemented")] - NotImplemented, - - #[error(transparent)] - Other(#[from] anyhow::Error), -} - -pub type Result = std::result::Result; - -// --- - -/// Helper extension trait to convert query results into [`re_types_core::Archetype`]s. -pub trait ToArchetype { - /// Converts the result into an [`re_types_core::Archetype`]. - /// - /// Automatically handles all aspects of the query process: deserialization, caching, promise - /// resolution, etc. - fn to_archetype( - &self, - resolver: &crate::PromiseResolver, - ) -> crate::PromiseResult>; -} diff --git a/crates/re_query2/src/range/mod.rs b/crates/re_query2/src/range/mod.rs deleted file mode 100644 index e4068c918b48..000000000000 --- a/crates/re_query2/src/range/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod query; -mod results; - -pub use self::query::range; -pub use self::results::{RangeComponentResults, RangeResults}; diff --git a/crates/re_query2/src/range/query.rs b/crates/re_query2/src/range/query.rs deleted file mode 100644 index 5c2c821bd846..000000000000 --- a/crates/re_query2/src/range/query.rs +++ /dev/null @@ -1,38 +0,0 @@ -use re_data_store::{DataStore, RangeQuery}; -use re_log_types::EntityPath; -use re_types_core::ComponentName; - -use crate::RangeResults; - -// --- - -/// Queries for the given `component_names` using range semantics. -/// -/// See [`RangeResults`] for more information about how to handle the results. -pub fn range( - store: &DataStore, - query: &RangeQuery, - entity_path: &EntityPath, - component_names: impl IntoIterator, -) -> RangeResults { - re_tracing::profile_function!(entity_path.to_string()); - - let mut results = RangeResults::default(); - - for component_name in component_names { - let data = store.range(query, entity_path, [component_name]).map( - |(data_time, row_id, mut cells)| { - // Unwrap: - // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` - // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null - let cell = cells[0].take().unwrap(); - - ((data_time, row_id), cell) - }, - ); - - results.add(component_name, data); - } - - results -} diff --git a/crates/re_query2/src/range/results.rs b/crates/re_query2/src/range/results.rs deleted file mode 100644 index 2cfe48751a7d..000000000000 --- a/crates/re_query2/src/range/results.rs +++ /dev/null @@ -1,204 +0,0 @@ -use nohash_hasher::IntMap; -use re_log_types::{DataCell, RowId, TimeInt}; -use re_types_core::ComponentName; -use re_types_core::{Component, DeserializationError, DeserializationResult}; - -use crate::{Promise, PromiseResolver, PromiseResult}; - -// --- - -/// Raw results for a range query. -/// -/// The data is neither deserialized, nor resolved/converted. -/// It it the raw [`DataCell`]s, straight from our datastore. -/// -/// Use [`RangeResults::get`], [`RangeResults::get_required`] and [`RangeResults::get_or_empty`] -/// in order to access the raw results for each individual component. -#[derive(Default, Debug, Clone)] -pub struct RangeResults { - /// Raw results for each individual component. - pub components: IntMap, -} - -impl RangeResults { - #[inline] - pub fn contains(&self, component_name: impl Into) -> bool { - self.components.contains_key(&component_name.into()) - } - - /// Returns the [`RangeComponentResults`] for the specified `component_name`. - #[inline] - pub fn get(&self, component_name: impl Into) -> Option<&RangeComponentResults> { - self.components.get(&component_name.into()) - } - - /// Returns the [`RangeComponentResults`] for the specified `component_name`. - /// - /// Returns an error if the component is not present. - #[inline] - pub fn get_required( - &self, - component_name: impl Into, - ) -> crate::Result<&RangeComponentResults> { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - Ok(component) - } else { - Err(DeserializationError::MissingComponent { - component: component_name, - backtrace: ::backtrace::Backtrace::new_unresolved(), - } - .into()) - } - } - - /// Returns the [`RangeComponentResults`] for the specified `component_name`. - /// - /// Returns empty results if the component is not present. - #[inline] - pub fn get_or_empty(&self, component_name: impl Into) -> &RangeComponentResults { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - component - } else { - static DEFAULT: RangeComponentResults = RangeComponentResults::empty(); - &DEFAULT - } - } -} - -impl RangeResults { - #[doc(hidden)] - #[inline] - pub fn add( - &mut self, - component_name: ComponentName, - data: impl Iterator, - ) { - let (indices, cells): (Vec<_>, Vec<_>) = data - .map(|(index, cell)| (index, Promise::new(cell))) - .unzip(); - - let results = RangeComponentResults { - indices, - promises: cells, - }; - results.sanity_check(); - - self.components.insert(component_name, results); - } -} - -// --- - -/// Uncached results for a particular component when using a range query. -#[derive(Debug, Clone)] -pub struct RangeComponentResults { - pub indices: Vec<(TimeInt, RowId)>, - pub promises: Vec, -} - -impl Default for RangeComponentResults { - #[inline] - fn default() -> Self { - Self::empty() - } -} - -impl RangeComponentResults { - #[inline] - pub const fn empty() -> Self { - Self { - indices: Vec::new(), - promises: Vec::new(), - } - } - - /// No-op in release. - #[inline] - pub fn sanity_check(&self) { - let Self { - indices, - promises: cells, - } = self; - if cfg!(debug_assertions) { - assert_eq!(indices.len(), cells.len()); - } - } -} - -impl RangeComponentResults { - #[inline] - pub fn indices(&self) -> &[(TimeInt, RowId)] { - &self.indices - } - - #[inline] - pub fn iter_indices(&self) -> impl ExactSizeIterator + '_ { - self.indices.iter().copied() - } - - /// Returns the component data as a vector of dense vectors. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_dense( - &self, - resolver: &PromiseResolver, - ) -> Vec>>> { - self.promises - .iter() - .map(|cell| { - resolver.resolve(cell).map(|cell| { - cell.try_to_native() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) - }) - .collect() - } - - /// Returns the component data as an iterator of dense vectors. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn iter_dense( - &self, - resolver: &PromiseResolver, - ) -> impl ExactSizeIterator>>> { - self.to_dense(resolver).into_iter() - } - - /// Returns the component data as a vector of sparse vectors. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_sparse( - &self, - resolver: &PromiseResolver, - ) -> Vec>>>> { - self.promises - .iter() - .map(|cell| { - resolver.resolve(cell).map(|cell| { - cell.try_to_native_opt() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) - }) - .collect() - } - - /// Returns the component data as an iterator of sparse vectors. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn iter_sparse( - &self, - resolver: &PromiseResolver, - ) -> impl ExactSizeIterator>>>> { - self.to_sparse(resolver).into_iter() - } -} diff --git a/crates/re_query2/tests/latest_at.rs b/crates/re_query2/tests/latest_at.rs deleted file mode 100644 index c5c4effde420..000000000000 --- a/crates/re_query2/tests/latest_at.rs +++ /dev/null @@ -1,217 +0,0 @@ -use re_data_store::DataStore; -use re_log_types::example_components::{MyColor, MyPoint, MyPoints}; -use re_log_types::{build_frame_nr, DataRow, RowId, TimePoint}; -use re_query2::PromiseResolver; -use re_types::components::InstanceKey; -use re_types::{Archetype as _, ComponentNameSet}; -use re_types_core::Loggable as _; - -// --- - -#[test] -fn simple_query() -> anyhow::Result<()> { - let resolver = PromiseResolver::default(); - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - let results = re_query2::latest_at( - &store, - &timeline_query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), - ); - - // We expect this to generate the following `DataFrame` - // ┌─────────────┬────────────┐ - // │ point ┆ color │ - // │ --- ┆ --- │ - // │ struct[2] ┆ u32 │ - // ╞═════════════╪════════════╡ - // │ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ 4278190080 │ - // └─────────────┴────────────┘ - - { - let expected_components: ComponentNameSet = - [MyPoint::name(), MyColor::name()].into_iter().collect(); - let got_components: ComponentNameSet = results.components.keys().copied().collect(); - similar_asserts::assert_eq!(expected_components, got_components); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = results.get_required(MyPoint::name())?; - let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - - let colors = results.get_or_empty(MyColor::name()); - let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} - -#[test] -fn static_query() -> anyhow::Result<()> { - let resolver = PromiseResolver::default(); - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, TimePoint::default(), 2, colors)?; - store.insert_row(&row)?; - - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - let results = re_query2::latest_at( - &store, - &timeline_query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), - ); - - // We expect this to generate the following `DataFrame` - // ┌───────────┬────────────┐ - // │ point ┆ color │ - // │ --- ┆ --- │ - // │ struct[2] ┆ u32 │ - // ╞═══════════╪════════════╡ - // │ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ 4278190080 │ - // └───────────┴────────────┘ - - { - let expected_components: ComponentNameSet = - [MyPoint::name(), MyColor::name()].into_iter().collect(); - let got_components: ComponentNameSet = results.components.keys().copied().collect(); - similar_asserts::assert_eq!(expected_components, got_components); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = results.get_required(MyPoint::name())?; - let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - - let colors = results.get_or_empty(MyColor::name()); - let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} - -#[test] -fn no_instance_join_query() -> anyhow::Result<()> { - let resolver = PromiseResolver::default(); - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, colors)?; - store.insert_row(&row)?; - - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - let results = re_query2::latest_at( - &store, - &timeline_query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), - ); - - // We expect this to generate the following `DataFrame` - // ┌───────────┬────────────┐ - // │ point ┆ color │ - // │ --- ┆ --- │ - // │ struct[2] ┆ u32 │ - // ╞═══════════╪════════════╡ - // │ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ 16711680 │ - // └───────────┴────────────┘ - - { - let expected_components: ComponentNameSet = - [MyPoint::name(), MyColor::name()].into_iter().collect(); - let got_components: ComponentNameSet = results.components.keys().copied().collect(); - similar_asserts::assert_eq!(expected_components, got_components); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(0, 255, 0)), - ]; - - let points = results.get_required(MyPoint::name())?; - let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - - let colors = results.get_or_empty(MyColor::name()); - let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} diff --git a/crates/re_query2/tests/range.rs b/crates/re_query2/tests/range.rs deleted file mode 100644 index a000f588b311..000000000000 --- a/crates/re_query2/tests/range.rs +++ /dev/null @@ -1,496 +0,0 @@ -use itertools::izip; -use re_query2::PromiseResolver; -use re_types::{components::InstanceKey, Archetype}; - -use re_data_store::{DataStore, TimeInt, TimeRange}; -use re_log_types::{ - build_frame_nr, - example_components::{MyColor, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimePoint, -}; -use re_types_core::Loggable as _; - -// --- - -#[test] -fn simple_range() -> anyhow::Result<()> { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let resolver = PromiseResolver::default(); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; - store.insert_row(&row)?; - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; - store.insert_row(&row)?; - } - - let timepoint3 = [build_frame_nr(323)]; - { - let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; - store.insert_row(&row)?; - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #323: - // ┌──────────────┬─────────────────┐ - // │ MyPoint ┆ MyColor │ - // ╞══════════════╪═════════════════╡ - // │ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {30.0,40.0} ┆ 4278190080 │ - // └──────────────┴─────────────────┘ - - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - assert!(results.next().is_none()); - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #123: - // ┌───────────────┬─────────────────┐ - // │ MyPoint ┆ MyColor │ - // ╞═══════════════╪═════════════════╡ - // │ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ null │ - // └───────────────┴─────────────────┘ - // - // Frame #323: - // ┌───────────────┬─────────────────┐ - // │ MyPoint ┆ MyColor │ - // ╞═══════════════╪═════════════════╡ - // │ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {30.0,40.0} ┆ 4278190080 │ - // └───────────────┴─────────────────┘ - - { - // Frame #123 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(123), data_time); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![None, None]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - assert!(results.next().is_none()); - - Ok(()) -} - -#[test] -fn static_range() -> anyhow::Result<()> { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let resolver = PromiseResolver::default(); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let mut row = - DataRow::from_cells1(RowId::new(), entity_path.clone(), timepoint1, 2, positions)?; - row.compute_all_size_bytes(); - store.insert_row(&row)?; - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances.clone(), colors.clone()), - )?; - store.insert_row(&row)?; - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(0)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances.clone(), colors.clone()), - )?; - store.insert_row(&row)?; - - // Insert statically too! - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - colors, - )?; - store.insert_row(&row)?; - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - timepoint3, - 2, - positions, - )?; - store.insert_row(&row)?; - } - - // ┌──────────┬───────────────┬────────────────────────────┐ - // │ frame_nr ┆ MyColor ┆ MyColor │ - // ╞══════════╪═══════════════╪════════════════════════════╡ - // │ null ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 123 ┆ null ┆ [{1.0,2.0}, {3.0,4.0}] │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 123 ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 223 ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 223 ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 323 ┆ null ┆ [{10.0,20.0}, {30.0,40.0}] │ - // └──────────┴───────────────┴────────────────────────────┘ - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - { - // Frame #123 (partially static) - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(123), data_time); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - // --- Third test: `[-inf, +inf]` --- - - let query = - re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - { - // Frame #123 (partially static) - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(123), data_time); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} diff --git a/crates/re_query_cache/Cargo.toml b/crates/re_query_cache/Cargo.toml deleted file mode 100644 index 71a9dfbe35ef..000000000000 --- a/crates/re_query_cache/Cargo.toml +++ /dev/null @@ -1,81 +0,0 @@ -[package] -name = "re_query_cache" -authors.workspace = true -description = "Caching datastructures for re_query" -edition.workspace = true -homepage.workspace = true -include.workspace = true -license.workspace = true -publish = true -readme = "README.md" -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[lints] -workspace = true - -[package.metadata.docs.rs] -all-features = true - - -[features] -default = ["to_archetype"] - -## Implements `ToArchetype` for all builtin archetypes on `CachedLatestAtResults`. -to_archetype = ["dep:re_types", "dep:re_types_blueprint"] - -[dependencies] -# Rerun dependencies: -re_data_store.workspace = true -re_error.workspace = true -re_format.workspace = true -re_log.workspace = true -re_log_types.workspace = true -re_query2.workspace = true -re_tracing.workspace = true -re_types_core.workspace = true - -# Rerun dependencies (optional): -re_types = { workspace = true, optional = true } -re_types_blueprint = { workspace = true, optional = true } - -# External dependencies: -ahash.workspace = true -anyhow.workspace = true -backtrace.workspace = true -indent.workspace = true -indexmap.workspace = true -itertools.workspace = true -nohash-hasher.workspace = true -parking_lot.workspace = true -paste.workspace = true -seq-macro.workspace = true -web-time.workspace = true - - -[dev-dependencies] -re_types = { workspace = true, features = ["datagen"] } - -criterion.workspace = true -mimalloc.workspace = true -rand = { workspace = true, features = ["std", "std_rng"] } -similar-asserts.workspace = true - - -[lib] -bench = false - - -[[example]] -name = "latest_at_archetype" -required-features = ["to_archetype"] - - -[[bench]] -name = "flat_vec_deque" -harness = false - -[[bench]] -name = "latest_at" -harness = false diff --git a/crates/re_query_cache/README.md b/crates/re_query_cache/README.md deleted file mode 100644 index 70613732471d..000000000000 --- a/crates/re_query_cache/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# re_query_cache - -Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. - -[![Latest version](https://img.shields.io/crates/v/re_query_cache.svg)](https://crates.io/crates/re_query_cache) -[![Documentation](https://docs.rs/re_query/badge.svg)](https://docs.rs/re_query) -![MIT](https://img.shields.io/badge/license-MIT-blue.svg) -![Apache](https://img.shields.io/badge/license-Apache-blue.svg) - -Caching datastructures for `re_query`. diff --git a/crates/re_query_cache/src/latest_at/mod.rs b/crates/re_query_cache/src/latest_at/mod.rs deleted file mode 100644 index 82fd889bce0b..000000000000 --- a/crates/re_query_cache/src/latest_at/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -mod helpers; -mod query; -mod results; - -#[cfg(feature = "to_archetype")] -mod to_archetype; - -pub use self::helpers::CachedLatestAtMonoResult; -pub use self::query::LatestAtCache; -pub use self::results::{CachedLatestAtComponentResults, CachedLatestAtResults}; diff --git a/crates/re_query_cache/src/lib.rs b/crates/re_query_cache/src/lib.rs deleted file mode 100644 index cb995ab447aa..000000000000 --- a/crates/re_query_cache/src/lib.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Caching datastructures for `re_query`. - -mod cache; -mod cache_stats; -mod flat_vec_deque; -mod latest_at; -mod range; - -pub use self::cache::{CacheKey, Caches}; -pub use self::cache_stats::{CachedComponentStats, CachesStats}; -pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; -pub use self::latest_at::{ - CachedLatestAtComponentResults, CachedLatestAtMonoResult, CachedLatestAtResults, -}; -pub use self::range::{CachedRangeComponentResults, CachedRangeData, CachedRangeResults}; - -pub(crate) use self::latest_at::LatestAtCache; -pub(crate) use self::range::{CachedRangeComponentResultsInner, RangeCache}; - -pub use re_query2::{ - clamped_zip::*, range_zip::*, ExtraQueryHistory, Promise, PromiseId, PromiseResolver, - PromiseResult, QueryError, Result, ToArchetype, VisibleHistory, VisibleHistoryBoundary, -}; - -pub mod external { - pub use re_query2; - - pub use paste; - pub use seq_macro; -} - -// --- - -use re_data_store::{LatestAtQuery, RangeQuery}; - -#[derive(Debug)] -pub enum CachedResults { - LatestAt(LatestAtQuery, CachedLatestAtResults), - Range(RangeQuery, CachedRangeResults), -} - -impl From<(LatestAtQuery, CachedLatestAtResults)> for CachedResults { - #[inline] - fn from((query, results): (LatestAtQuery, CachedLatestAtResults)) -> Self { - Self::LatestAt(query, results) - } -} - -impl From<(RangeQuery, CachedRangeResults)> for CachedResults { - #[inline] - fn from((query, results): (RangeQuery, CachedRangeResults)) -> Self { - Self::Range(query, results) - } -} diff --git a/crates/re_query_cache/src/range/mod.rs b/crates/re_query_cache/src/range/mod.rs deleted file mode 100644 index ffb93dd2f720..000000000000 --- a/crates/re_query_cache/src/range/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod query; -mod results; - -pub use self::query::RangeCache; -pub use self::results::{ - CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeData, - CachedRangeResults, -}; diff --git a/crates/re_query_cache/tests/latest_at.rs b/crates/re_query_cache/tests/latest_at.rs deleted file mode 100644 index 4073c5ec7e53..000000000000 --- a/crates/re_query_cache/tests/latest_at.rs +++ /dev/null @@ -1,526 +0,0 @@ -//! Contains: -//! - A 1:1 port of the tests in `crates/re_query/tests/archetype_query_tests.rs`, with caching enabled. -//! - Invalidation tests. - -use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; -use re_log_types::{ - build_frame_nr, - example_components::{MyColor, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimePoint, -}; -use re_query2::PromiseResolver; -use re_query_cache::Caches; -use re_types::Archetype as _; -use re_types_core::{components::InstanceKey, Loggable as _}; - -// --- - -#[test] -fn simple_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn static_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance.. statically! - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - TimePoint::default(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn no_instance_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign them colors with explicit instances - let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn missing_column_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn splatted_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign all of them a color via splat - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn invalidation() { - let entity_path = "point"; - - let test_invalidation = |query: LatestAtQuery, - present_data_timepoint: TimePoint, - past_data_timepoint: TimePoint, - future_data_timepoint: TimePoint| { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(1, 2, 3)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify present --- - - // Modify the PoV component - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint, - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify past --- - - // Modify the PoV component - let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, past_data_timepoint, 2, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify future --- - - // Modify the PoV component - let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - future_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(16, 17, 18)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - }; - - let timeless = TimePoint::default(); - let frame_122 = build_frame_nr(122); - let frame_123 = build_frame_nr(123); - let frame_124 = build_frame_nr(124); - - test_invalidation( - LatestAtQuery::new(frame_123.0, frame_123.1), - [frame_123].into(), - [frame_122].into(), - [frame_124].into(), - ); - - test_invalidation( - LatestAtQuery::new(frame_123.0, frame_123.1), - [frame_123].into(), - timeless, - [frame_124].into(), - ); -} - -// Test the following scenario: -// ```py -// rr.log("points", rr.Points3D([1, 2, 3]), static=True) -// -// # Do first query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[] -// -// rr.set_time(2) -// rr.log_components("points", rr.components.MyColor(0xFF0000)) -// -// # Do second query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0xFF0000] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x0000FF)) -// -// # Do third query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x0000FF] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x00FF00)) -// -// # Do fourth query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x00FF00] -// ``` -#[test] -fn invalidation_of_future_optionals() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - let frame2 = [build_frame_nr(2)]; - let frame3 = [build_frame_nr(3)]; - - let query_time = [build_frame_nr(9999)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame2, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame3, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame3, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn static_invalidation() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - - let query_time = [build_frame_nr(9999)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timeless.clone(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timeless, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -// --- - -fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { - caches.on_events(&[store.insert_row(row).unwrap()]); -} - -fn query_and_compare( - caches: &Caches, - store: &DataStore, - query: &LatestAtQuery, - entity_path: &EntityPath, -) { - re_log::setup_logging(); - - let resolver = PromiseResolver::default(); - - for _ in 0..3 { - let cached = caches.latest_at( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let cached_points = cached.get_required(MyPoint::name()).unwrap(); - let cached_point_data = cached_points - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let cached_colors = cached.get_or_empty(MyColor::name()); - let cached_color_data = cached_colors - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let expected = re_query2::latest_at( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let expected_points = expected.get_required(MyPoint::name()).unwrap(); - let expected_point_data = expected_points - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let expected_colors = expected.get_or_empty(MyColor::name()); - let expected_color_data = expected_colors - .to_dense::(&resolver) - .flatten() - .unwrap(); - - // eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!(expected.compound_index, cached.compound_index); - similar_asserts::assert_eq!(expected_point_data, cached_point_data); - similar_asserts::assert_eq!(expected_color_data, cached_color_data); - } -} diff --git a/crates/re_query_cache/tests/range.rs b/crates/re_query_cache/tests/range.rs deleted file mode 100644 index eb7380c8a1d0..000000000000 --- a/crates/re_query_cache/tests/range.rs +++ /dev/null @@ -1,586 +0,0 @@ -use itertools::{izip, Itertools as _}; - -use re_data_store::{DataStore, RangeQuery, StoreSubscriber as _, TimeInt, TimeRange}; -use re_log_types::{ - build_frame_nr, - example_components::{MyColor, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimePoint, -}; -use re_query_cache::{Caches, PromiseResolver, PromiseResult}; -use re_types::{components::InstanceKey, Archetype}; -use re_types_core::Loggable as _; - -// --- - -#[test] -fn simple_range() -> anyhow::Result<()> { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - Ok(()) -} - -#[test] -fn static_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - colors.clone(), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Insert statically too! - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - colors.clone(), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Insert statically too! - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - // The inclusion of `timepoint1` means latest-at semantics will fall back to timeless data! - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Third test: `[-inf, +inf]` --- - - let query = - re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); - - query_and_compare(&caches, &store, &query, &entity_path); -} - -#[test] -fn simple_splatted_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); -} - -#[test] -fn invalidation() { - let entity_path = "point"; - - let test_invalidation = |query: RangeQuery, - present_data_timepoint: TimePoint, - past_data_timepoint: TimePoint, - future_data_timepoint: TimePoint| { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(1, 2, 3)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify present --- - - // Modify the PoV component - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint, - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify past --- - - // Modify the PoV component - let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify future --- - - // Modify the PoV component - let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - future_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(16, 17, 18)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - }; - - let timeless = TimePoint::default(); - let frame_122 = build_frame_nr(122); - let frame_123 = build_frame_nr(123); - let frame_124 = build_frame_nr(124); - - test_invalidation( - RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), - [frame_123].into(), - [frame_122].into(), - [frame_124].into(), - ); - - test_invalidation( - RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), - [frame_123].into(), - timeless, - [frame_124].into(), - ); -} - -// Test the following scenario: -// ```py -// rr.log("points", rr.Points3D([1, 2, 3]), static=True) -// -// # Do first query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[] -// -// rr.set_time(2) -// rr.log_components("points", rr.components.MyColor(0xFF0000)) -// -// # Do second query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0xFF0000] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x0000FF)) -// -// # Do third query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x0000FF] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x00FF00)) -// -// # Do fourth query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x00FF00] -// ``` -#[test] -fn invalidation_of_future_optionals() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - let frame2 = [build_frame_nr(2)]; - let frame3 = [build_frame_nr(3)]; - - let query = re_data_store::RangeQuery::new(frame2[0].0, TimeRange::EVERYTHING); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn invalidation_static() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - - let frame0 = [build_frame_nr(TimeInt::ZERO)]; - let query = re_data_store::RangeQuery::new(frame0[0].0, TimeRange::EVERYTHING); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -// --- - -fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { - caches.on_events(&[store.insert_row(row).unwrap()]); -} - -fn query_and_compare( - caches: &Caches, - store: &DataStore, - query: &RangeQuery, - entity_path: &EntityPath, -) { - re_log::setup_logging(); - - let resolver = PromiseResolver::default(); - - for _ in 0..3 { - let cached = caches.range( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let cached_all_points = cached - .get_required(MyPoint::name()) - .unwrap() - .to_dense::(&resolver); - assert!(matches!( - cached_all_points.status(), - (PromiseResult::Ready(()), PromiseResult::Ready(())), - )); - let cached_all_points_indexed = cached_all_points.range_indexed(); - - let cached_all_colors = cached - .get_or_empty(MyColor::name()) - .to_dense::(&resolver); - assert!(matches!( - cached_all_colors.status(), - (PromiseResult::Ready(()), PromiseResult::Ready(())), - )); - let cached_all_colors_indexed = cached_all_colors.range_indexed(); - - let expected = re_query2::range( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let expected_all_points = expected.get_required(MyPoint::name()).unwrap(); - let expected_all_points_indices = expected_all_points.indices(); - let expected_all_points_data = expected_all_points - .to_dense::(&resolver) - .into_iter() - .map(|batch| batch.flatten().unwrap()) - .collect_vec(); - let expected_all_points_indexed = - izip!(expected_all_points_indices, expected_all_points_data); - - let expected_all_colors = expected.get_or_empty(MyColor::name()); - let expected_all_colors_indices = expected_all_colors.indices(); - let expected_all_colors_data = expected_all_colors - .to_dense::(&resolver) - .into_iter() - .map(|batch| batch.flatten().unwrap()) - .collect_vec(); - let expected_all_colors_indexed = - izip!(expected_all_colors_indices, expected_all_colors_data); - - eprintln!("{query:?}"); - eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!( - expected_all_points_indexed - .map(|(index, data)| (*index, data)) - .collect_vec(), - cached_all_points_indexed - .map(|(index, data)| (*index, data.to_vec())) - .collect_vec(), - ); - - similar_asserts::assert_eq!( - expected_all_colors_indexed - .map(|(index, data)| (*index, data)) - .collect_vec(), - cached_all_colors_indexed - .map(|(index, data)| (*index, data.to_vec())) - .collect_vec(), - ); - } -} diff --git a/crates/re_space_view/Cargo.toml b/crates/re_space_view/Cargo.toml index 441e96bc95ea..36b53d591f51 100644 --- a/crates/re_space_view/Cargo.toml +++ b/crates/re_space_view/Cargo.toml @@ -27,7 +27,6 @@ re_log_types.workspace = true re_data_store.workspace = true re_entity_db.workspace = true re_query.workspace = true -re_query_cache.workspace = true re_tracing.workspace = true re_types_core.workspace = true re_types.workspace = true diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index cd9b86fa22d7..8e435edeb682 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -1,6 +1,6 @@ use itertools::{FoldWhile, Itertools}; use nohash_hasher::IntMap; -use re_entity_db::external::re_query_cache::PromiseResult; +use re_entity_db::external::re_query::PromiseResult; use crate::SpaceViewContents; use re_data_store::LatestAtQuery; diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 2b4e94cd853e..82116aef381e 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -3,7 +3,7 @@ use slotmap::SlotMap; use smallvec::SmallVec; use re_entity_db::{ - external::{re_data_store::LatestAtQuery, re_query_cache::PromiseResult}, + external::{re_data_store::LatestAtQuery, re_query::PromiseResult}, EntityDb, EntityProperties, EntityPropertiesComponent, EntityPropertyMap, EntityTree, }; use re_log_types::{ diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 198f150f1430..2325aa3b2868 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -1,6 +1,6 @@ use re_data_store::LatestAtQuery; use re_entity_db::{ - external::re_query_cache::{CachedLatestAtResults, PromiseResult, ToArchetype}, + external::re_query::{LatestAtResults, PromiseResult, ToArchetype}, EntityDb, }; use re_log_types::EntityPath; @@ -46,7 +46,7 @@ pub fn query_space_view_sub_archetype( query: &LatestAtQuery, ) -> (PromiseResult>, EntityPath) where - CachedLatestAtResults: ToArchetype, + LatestAtResults: ToArchetype, { let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); ( @@ -63,7 +63,7 @@ pub fn query_space_view_sub_archetype_or_default( query: &LatestAtQuery, ) -> (A, EntityPath) where - CachedLatestAtResults: ToArchetype, + LatestAtResults: ToArchetype, { let (arch, path) = query_space_view_sub_archetype(space_view_id, blueprint_db, query); (arch.ok().flatten().unwrap_or_default(), path) diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs index 2c2af59f7363..4a55c27e31f9 100644 --- a/crates/re_space_view/src/visual_time_range.rs +++ b/crates/re_space_view/src/visual_time_range.rs @@ -8,7 +8,7 @@ //! to reduce the amount of changes in code that is likely to be refactored soon anyways. use re_log_types::TimeRange; -use re_query_cache::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; use re_types::blueprint::{ components::VisibleTimeRange, datatypes::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}, diff --git a/crates/re_space_view_dataframe/Cargo.toml b/crates/re_space_view_dataframe/Cargo.toml index 7ba423482c19..aab59723a55b 100644 --- a/crates/re_space_view_dataframe/Cargo.toml +++ b/crates/re_space_view_dataframe/Cargo.toml @@ -24,7 +24,6 @@ re_data_ui.workspace = true re_entity_db.workspace = true re_log_types.workspace = true re_query.workspace = true -re_query_cache.workspace = true re_renderer.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_space_view_spatial/Cargo.toml b/crates/re_space_view_spatial/Cargo.toml index 2bf7b4745914..57aa3d632a16 100644 --- a/crates/re_space_view_spatial/Cargo.toml +++ b/crates/re_space_view_spatial/Cargo.toml @@ -27,7 +27,6 @@ re_format.workspace = true re_log_types.workspace = true re_log.workspace = true re_query.workspace = true -re_query_cache.workspace = true re_renderer = { workspace = true, features = [ "import-gltf", "import-obj", diff --git a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs index f7ed6472e5de..b274db0b8b97 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x6; +use re_query::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows2D, @@ -220,7 +220,7 @@ impl VisualizerSystem for Arrows2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs index 05fdb1ef9764..cf59264e9401 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x6; +use re_query::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows3D, @@ -223,7 +223,7 @@ impl VisualizerSystem for Arrows3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/assets3d.rs b/crates/re_space_view_spatial/src/visualizers/assets3d.rs index fd14f33490a1..77d22a2a4d93 100644 --- a/crates/re_space_view_spatial/src/visualizers/assets3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/assets3d.rs @@ -1,6 +1,6 @@ use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query_cache::range_zip_1x2; +use re_query::range_zip_1x2; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Asset3D, @@ -143,7 +143,7 @@ impl VisualizerSystem for Asset3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs index 07fb7d9b9acd..dc4588ff9746 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x6; +use re_query::range_zip_1x6; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes2D, @@ -216,7 +216,7 @@ impl VisualizerSystem for Boxes2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs index 8819231a5aea..2dfcd63d95cf 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x7; +use re_query::range_zip_1x7; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes3D, @@ -206,7 +206,7 @@ impl VisualizerSystem for Boxes3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 7b341e5064a6..6b5c39bf70ed 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -2,7 +2,7 @@ use itertools::Either; use re_data_store::{LatestAtQuery, RangeQuery}; use re_entity_db::{EntityDb, EntityProperties}; use re_log_types::{EntityPath, TimeInt, Timeline}; -use re_query_cache::{CachedResults, ExtraQueryHistory}; +use re_query::{ExtraQueryHistory, Results}; use re_renderer::DepthOffset; use re_space_view::query_visual_history; use re_types::Archetype; @@ -46,7 +46,7 @@ pub fn query_archetype_with_history( time: &TimeInt, history: &ExtraQueryHistory, entity_path: &EntityPath, -) -> CachedResults { +) -> Results { let visible_history = match timeline.typ() { re_log_types::TimeType::Time => history.nanos, re_log_types::TimeType::Sequence => history.sequences, @@ -96,7 +96,7 @@ where &EntityPath, &EntityProperties, &SpatialSceneEntityContext<'_>, - &CachedResults, + &Results, ) -> Result<(), SpaceViewSystemExecutionError>, { let transforms = view_ctx.get::()?; diff --git a/crates/re_space_view_spatial/src/visualizers/images.rs b/crates/re_space_view_spatial/src/visualizers/images.rs index 82ef54742c40..54fc1a9919e6 100644 --- a/crates/re_space_view_spatial/src/visualizers/images.rs +++ b/crates/re_space_view_spatial/src/visualizers/images.rs @@ -6,7 +6,7 @@ use nohash_hasher::IntSet; use re_entity_db::{EntityPath, EntityProperties}; use re_log_types::{EntityPathHash, RowId, TimeInt}; -use re_query_cache::range_zip_1x2; +use re_query::range_zip_1x2; use re_renderer::{ renderer::{DepthCloud, DepthClouds, RectangleOptions, TexturedRect}, Colormap, @@ -855,7 +855,7 @@ impl ImageVisualizer { |ctx, entity_path, entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/lines2d.rs b/crates/re_space_view_spatial/src/visualizers/lines2d.rs index e7c688eab4a7..bbddd23851d6 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::LineStrips2D, @@ -205,7 +205,7 @@ impl VisualizerSystem for Lines2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/lines3d.rs b/crates/re_space_view_spatial/src/visualizers/lines3d.rs index 9bbb657425f9..e4da2c12ce24 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::PickingLayerInstanceId; use re_types::{ archetypes::LineStrips3D, @@ -214,7 +214,7 @@ impl VisualizerSystem for Lines3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/meshes.rs b/crates/re_space_view_spatial/src/visualizers/meshes.rs index 89d28eadd512..5ac9b2a3a48b 100644 --- a/crates/re_space_view_spatial/src/visualizers/meshes.rs +++ b/crates/re_space_view_spatial/src/visualizers/meshes.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query_cache::range_zip_1x7; +use re_query::range_zip_1x7; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Mesh3D, @@ -168,7 +168,7 @@ impl VisualizerSystem for Mesh3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/mod.rs b/crates/re_space_view_spatial/src/visualizers/mod.rs index 98e205ec4ab7..62745ee750f2 100644 --- a/crates/re_space_view_spatial/src/visualizers/mod.rs +++ b/crates/re_space_view_spatial/src/visualizers/mod.rs @@ -22,7 +22,7 @@ pub use images::{ImageVisualizer, ViewerImage}; pub use spatial_view_visualizer::SpatialViewVisualizerData; pub use transform3d_arrows::{add_axis_arrows, Transform3DArrowsVisualizer}; -pub(crate) use self::results_ext::CachedRangeResultsExt; +pub(crate) use self::results_ext::RangeResultsExt; // --- diff --git a/crates/re_space_view_spatial/src/visualizers/points2d.rs b/crates/re_space_view_spatial/src/visualizers/points2d.rs index 31bc5389316c..3ac152c1184e 100644 --- a/crates/re_space_view_spatial/src/visualizers/points2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points2d.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points2D, @@ -224,7 +224,7 @@ impl VisualizerSystem for Points2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/points3d.rs b/crates/re_space_view_spatial/src/visualizers/points3d.rs index 2d70126c2c5b..98e2ce7da604 100644 --- a/crates/re_space_view_spatial/src/visualizers/points3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points3d.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points3D, @@ -215,7 +215,7 @@ impl VisualizerSystem for Points3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/results_ext.rs b/crates/re_space_view_spatial/src/visualizers/results_ext.rs index 27474a9cc886..1b03697315b6 100644 --- a/crates/re_space_view_spatial/src/visualizers/results_ext.rs +++ b/crates/re_space_view_spatial/src/visualizers/results_ext.rs @@ -1,7 +1,4 @@ -use re_query_cache::{ - CachedLatestAtResults, CachedRangeData, CachedRangeResults, CachedResults, PromiseResolver, - PromiseResult, -}; +use re_query::{LatestAtResults, PromiseResolver, PromiseResult, RangeData, RangeResults, Results}; use re_types::Component; // --- @@ -10,60 +7,56 @@ use re_types::Component; /// /// Also turns all results into range results, so that views only have to worry about the ranged /// case. -pub trait CachedRangeResultsExt { +pub trait RangeResultsExt { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>>; + ) -> Option>>; fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result>; + ) -> re_query::Result>; } -impl CachedRangeResultsExt for CachedResults { +impl RangeResultsExt for Results { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { match self { - CachedResults::LatestAt(_, results) => results.get_dense(resolver), - CachedResults::Range(_, results) => results.get_dense(resolver), + Results::LatestAt(_, results) => results.get_dense(resolver), + Results::Range(_, results) => results.get_dense(resolver), } } fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result> { + ) -> re_query::Result> { match self { - CachedResults::LatestAt(_, results) => results.get_or_empty_dense(resolver), - CachedResults::Range(_, results) => results.get_or_empty_dense(resolver), + Results::LatestAt(_, results) => results.get_or_empty_dense(resolver), + Results::Range(_, results) => results.get_or_empty_dense(resolver), } } } -impl CachedRangeResultsExt for CachedRangeResults { +impl RangeResultsExt for RangeResults { #[inline] fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?.to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = results.status(); match front_status { - PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -74,17 +67,17 @@ impl CachedRangeResultsExt for CachedRangeResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result> { + ) -> re_query::Result> { let results = self.get_or_empty(C::name()).to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = results.status(); match front_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -92,27 +85,23 @@ impl CachedRangeResultsExt for CachedRangeResults { } } -impl CachedRangeResultsExt for CachedLatestAtResults { +impl RangeResultsExt for LatestAtResults { #[inline] fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?; - let data = CachedRangeData::from_latest_at(resolver, results); + let data = RangeData::from_latest_at(resolver, results); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); match front_status { - PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -123,18 +112,18 @@ impl CachedRangeResultsExt for CachedLatestAtResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result> { + ) -> re_query::Result> { let results = self.get_or_empty(C::name()); - let data = CachedRangeData::from_latest_at(resolver, results); + let data = RangeData::from_latest_at(resolver, results); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); match front_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } diff --git a/crates/re_space_view_tensor/src/visualizer_system.rs b/crates/re_space_view_tensor/src/visualizer_system.rs index b22578d5da31..c0f0bfb05018 100644 --- a/crates/re_space_view_tensor/src/visualizer_system.rs +++ b/crates/re_space_view_tensor/src/visualizer_system.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::CachedLatestAtMonoResult, EntityPath}; +use re_entity_db::{external::re_query::LatestAtMonoResult, EntityPath}; use re_log_types::RowId; use re_types::{archetypes::Tensor, components::TensorData, tensor_data::DecodedTensor}; use re_viewer_context::{ @@ -56,7 +56,7 @@ impl TensorSystem { &mut self, ctx: &ViewerContext<'_>, ent_path: &EntityPath, - tensor: CachedLatestAtMonoResult, + tensor: LatestAtMonoResult, ) { let row_id = tensor.row_id(); match ctx diff --git a/crates/re_space_view_text_document/Cargo.toml b/crates/re_space_view_text_document/Cargo.toml index b924d7ab60de..70a369abfa45 100644 --- a/crates/re_space_view_text_document/Cargo.toml +++ b/crates/re_space_view_text_document/Cargo.toml @@ -26,7 +26,6 @@ markdown = ["dep:egui_commonmark"] [dependencies] re_data_store.workspace = true re_log.workspace = true -re_query.workspace = true re_renderer.workspace = true re_space_view.workspace = true re_tracing.workspace = true diff --git a/crates/re_space_view_text_document/src/visualizer_system.rs b/crates/re_space_view_text_document/src/visualizer_system.rs index 75e06692813c..057dc85b1aee 100644 --- a/crates/re_space_view_text_document/src/visualizer_system.rs +++ b/crates/re_space_view_text_document/src/visualizer_system.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_space_view::external::re_query_cache::PromiseResult; +use re_space_view::external::re_query::PromiseResult; use re_types::{archetypes::TextDocument, components}; use re_viewer_context::{ IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, diff --git a/crates/re_space_view_text_log/Cargo.toml b/crates/re_space_view_text_log/Cargo.toml index d1343494859e..0d277c329970 100644 --- a/crates/re_space_view_text_log/Cargo.toml +++ b/crates/re_space_view_text_log/Cargo.toml @@ -24,7 +24,7 @@ re_data_ui.workspace = true re_entity_db.workspace = true re_log_types.workspace = true re_log.workspace = true -re_query_cache.workspace = true +re_query.workspace = true re_renderer.workspace = true re_tracing.workspace = true re_types.workspace = true diff --git a/crates/re_space_view_text_log/src/visualizer_system.rs b/crates/re_space_view_text_log/src/visualizer_system.rs index a06212b65488..642a4a023309 100644 --- a/crates/re_space_view_text_log/src/visualizer_system.rs +++ b/crates/re_space_view_text_log/src/visualizer_system.rs @@ -1,7 +1,7 @@ use re_data_store::TimeRange; use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query_cache::{clamped_zip_1x2, range_zip_1x2, CachedRangeData, PromiseResult}; +use re_query::{clamped_zip_1x2, range_zip_1x2, PromiseResult, RangeData}; use re_types::{ archetypes::TextLog, components::{Color, Text, TextLogLevel}, @@ -127,18 +127,16 @@ impl VisualizerSystem for TextLogSystem { // TODO(#5607): what should happen if the promise is still pending? #[inline] -fn check_range<'a, C: Component>( - results: &'a CachedRangeData<'a, C>, -) -> re_query_cache::Result<()> { +fn check_range<'a, C: Component>(results: &'a RangeData<'a, C>) -> re_query::Result<()> { let (front_status, back_status) = results.status(); match front_status { PromiseResult::Pending => return Ok(()), - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Ready(_) => {} } match back_status { PromiseResult::Pending => return Ok(()), - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Ready(_) => {} } diff --git a/crates/re_space_view_time_series/Cargo.toml b/crates/re_space_view_time_series/Cargo.toml index 16faadc51266..bcbfc845c815 100644 --- a/crates/re_space_view_time_series/Cargo.toml +++ b/crates/re_space_view_time_series/Cargo.toml @@ -24,7 +24,6 @@ re_format.workspace = true re_log.workspace = true re_log_types.workspace = true re_query.workspace = true -re_query_cache.workspace = true re_renderer.workspace = true re_space_view.workspace = true re_tracing.workspace = true diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 814f7369d249..5525f0ec0db8 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -1,5 +1,5 @@ use itertools::Itertools as _; -use re_query_cache::{PromiseResult, QueryError}; +use re_query::{PromiseResult, QueryError}; use re_types::archetypes; use re_types::{ archetypes::SeriesLine, @@ -259,7 +259,7 @@ fn load_series( .map(|index| (index, ())); let all_frames = - re_query_cache::range_zip_1x1(all_scalars_indexed, all_colors.range_indexed()) + re_query::range_zip_1x1(all_scalars_indexed, all_colors.range_indexed()) .enumerate(); for (i, (_index, _scalars, colors)) in all_frames { @@ -296,11 +296,9 @@ fn load_series( .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( - all_scalars_indexed, - all_stroke_widths.range_indexed(), - ) - .enumerate(); + let all_frames = + re_query::range_zip_1x1(all_scalars_indexed, all_stroke_widths.range_indexed()) + .enumerate(); for (i, (_index, _scalars, stroke_widths)) in all_frames { if let Some(stroke_width) = diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index 6b5b0c997ed7..6bfeca20cd0e 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -1,6 +1,6 @@ use itertools::Itertools as _; -use re_query_cache::{PromiseResult, QueryError}; +use re_query::{PromiseResult, QueryError}; use re_types::{ archetypes::{self, SeriesPoint}, components::{Color, MarkerShape, MarkerSize, Name, Scalar}, @@ -217,7 +217,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( + let all_frames = re_query::range_zip_1x1( all_scalars_indexed, all_colors.range_indexed(), ) @@ -257,7 +257,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( + let all_frames = re_query::range_zip_1x1( all_scalars_indexed, all_marker_sizes.range_indexed(), ) @@ -289,7 +289,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( + let all_frames = re_query::range_zip_1x1( all_scalars_indexed, all_marker_shapes.range_indexed(), ) diff --git a/crates/re_types_builder/src/codegen/rust/to_archetype.rs b/crates/re_types_builder/src/codegen/rust/to_archetype.rs index fac93e1fed22..af38e603a5d8 100644 --- a/crates/re_types_builder/src/codegen/rust/to_archetype.rs +++ b/crates/re_types_builder/src/codegen/rust/to_archetype.rs @@ -1,4 +1,4 @@ -//! Generates code in `re_query_cache` so that cached results can easily be converted to +//! Generates code in `re_query` so that cached results can easily be converted to //! ready-to-use archetypes. //! //! That code needs to be generated directly in the caching crates as it needs access to the cached @@ -34,8 +34,7 @@ fn generate_mod( objects: &Objects, files_to_write: &mut BTreeMap, ) { - let generated_path = - Utf8PathBuf::from("crates/re_query_cache/src/latest_at/to_archetype/mod.rs"); + let generated_path = Utf8PathBuf::from("crates/re_query/src/latest_at/to_archetype/mod.rs"); let mut code = String::new(); code.push_str(&format!("// {}\n\n", crate::codegen::autogen_warning!())); @@ -62,15 +61,14 @@ fn generate_impls( objects: &Objects, files_to_write: &mut BTreeMap, ) { - let generated_path = Utf8PathBuf::from("crates/re_query_cache/src/latest_at/to_archetype"); + let generated_path = Utf8PathBuf::from("crates/re_query/src/latest_at/to_archetype"); let quoted_imports = quote! { use std::sync::Arc; - use re_query2::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; - use crate::CachedLatestAtResults; + use crate::{LatestAtResults, PromiseResolver, PromiseResult}; }; for obj in objects.ordered_objects(Some(ObjectKind::Archetype)) { @@ -239,7 +237,7 @@ fn quote_to_archetype_impl(objects: &Objects, obj: &Object) -> TokenStream { }); quote! { - impl crate::ToArchetype<#quoted_arch_fqname> for CachedLatestAtResults { + impl crate::ToArchetype<#quoted_arch_fqname> for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_viewer/Cargo.toml b/crates/re_viewer/Cargo.toml index 2168bec9fe30..3db7e4dcebef 100644 --- a/crates/re_viewer/Cargo.toml +++ b/crates/re_viewer/Cargo.toml @@ -53,7 +53,7 @@ re_log_encoding = { workspace = true, features = [ ] } re_log_types.workspace = true re_memory.workspace = true -re_query_cache.workspace = true +re_query.workspace = true re_renderer = { workspace = true, default-features = false } re_smart_channel.workspace = true re_space_view.workspace = true diff --git a/crates/re_viewer/src/lib.rs b/crates/re_viewer/src/lib.rs index 85b2747bf3e1..54344896001c 100644 --- a/crates/re_viewer/src/lib.rs +++ b/crates/re_viewer/src/lib.rs @@ -34,8 +34,8 @@ pub mod external { pub use {eframe, egui}; pub use { re_data_store, re_data_store::external::*, re_entity_db, re_log, re_log_types, re_memory, - re_query_cache, re_renderer, re_types, re_ui, re_viewer_context, - re_viewer_context::external::*, re_viewport, re_viewport::external::*, + re_query, re_renderer, re_types, re_ui, re_viewer_context, re_viewer_context::external::*, + re_viewport, re_viewport::external::*, }; } diff --git a/crates/re_viewer/src/ui/memory_panel.rs b/crates/re_viewer/src/ui/memory_panel.rs index d60b680732b3..e7a434e77cb0 100644 --- a/crates/re_viewer/src/ui/memory_panel.rs +++ b/crates/re_viewer/src/ui/memory_panel.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use re_data_store::{DataStoreConfig, DataStoreRowStats, DataStoreStats}; use re_format::{format_bytes, format_uint}; use re_memory::{util::sec_since_start, MemoryHistory, MemoryLimit, MemoryUse}; -use re_query_cache::{CachedComponentStats, CachesStats}; +use re_query::{CachedComponentStats, CachesStats}; use re_renderer::WgpuResourcePoolStatistics; use re_viewer_context::store_hub::StoreHubStats; diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index 835b3c5aec4c..f90f05f6eb63 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -24,7 +24,6 @@ re_data_store.workspace = true re_entity_db = { workspace = true, features = ["serde"] } re_log_types.workspace = true re_log.workspace = true -re_query_cache.workspace = true re_query.workspace = true re_renderer.workspace = true re_smart_channel.workspace = true diff --git a/crates/re_viewer_context/src/component_ui_registry.rs b/crates/re_viewer_context/src/component_ui_registry.rs index 85acff5c5f77..756870c051ea 100644 --- a/crates/re_viewer_context/src/component_ui_registry.rs +++ b/crates/re_viewer_context/src/component_ui_registry.rs @@ -1,9 +1,7 @@ use std::collections::BTreeMap; use re_data_store::LatestAtQuery; -use re_entity_db::{ - external::re_query_cache::CachedLatestAtComponentResults, EntityDb, EntityPath, -}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb, EntityPath}; use re_log_types::DataCell; use re_types::{components::InstanceKey, ComponentName, Loggable as _}; @@ -42,7 +40,7 @@ type ComponentUiCallback = Box< &LatestAtQuery, &EntityDb, &EntityPath, - &CachedLatestAtComponentResults, + &LatestAtComponentResults, &InstanceKey, ) + Send + Sync, @@ -57,7 +55,7 @@ type ComponentEditCallback = Box< &EntityDb, &EntityPath, &EntityPath, - &CachedLatestAtComponentResults, + &LatestAtComponentResults, &InstanceKey, ) + Send + Sync, @@ -122,7 +120,7 @@ impl ComponentUiRegistry { query: &LatestAtQuery, db: &EntityDb, entity_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &InstanceKey, ) { let Some(component_name) = component.component_name(db.resolver()) else { @@ -165,7 +163,7 @@ impl ComponentUiRegistry { db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &InstanceKey, ) { let Some(component_name) = component.component_name(db.resolver()) else { diff --git a/crates/re_viewer_context/src/item.rs b/crates/re_viewer_context/src/item.rs index 0d21d88d3dfd..3fbdee8ca299 100644 --- a/crates/re_viewer_context/src/item.rs +++ b/crates/re_viewer_context/src/item.rs @@ -199,8 +199,7 @@ pub fn resolve_mono_instance_path( [component], ); if let Some(results) = results.get(component) { - if let re_query_cache::PromiseResult::Ready(cell) = - results.resolved(entity_db.resolver()) + if let re_query::PromiseResult::Ready(cell) = results.resolved(entity_db.resolver()) { if cell.num_instances() > 1 { return instance.clone(); diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 17632a2aa4ff..b4da1ba5f82b 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -48,9 +48,6 @@ pub enum SpaceViewSystemExecutionError { #[error(transparent)] QueryError(#[from] re_query::QueryError), - #[error(transparent)] - QueryError2(#[from] re_query_cache::QueryError), - #[error(transparent)] DeserializationError(#[from] re_types::DeserializationError), diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index f90c08ee3611..0160a1a14915 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -7,7 +7,7 @@ use re_data_store::StoreGeneration; use re_data_store::{DataStoreConfig, DataStoreStats}; use re_entity_db::{EntityDb, StoreBundle}; use re_log_types::{ApplicationId, StoreId, StoreKind}; -use re_query_cache::CachesStats; +use re_query::CachesStats; use crate::StoreContext; diff --git a/crates/re_viewport/src/container.rs b/crates/re_viewport/src/container.rs index b5e2381ef41f..15a2f3b83011 100644 --- a/crates/re_viewport/src/container.rs +++ b/crates/re_viewport/src/container.rs @@ -2,7 +2,7 @@ use ahash::HashMap; use egui_tiles::TileId; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::PromiseResult, EntityDb}; +use re_entity_db::{external::re_query::PromiseResult, EntityDb}; use re_log::ResultExt; use re_log_types::{DataRow, EntityPath, RowId}; use re_types::blueprint::components::Visible; diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index f0cb5f83d587..e608e63a6805 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -7,7 +7,7 @@ use nohash_hasher::IntSet; use smallvec::SmallVec; use re_data_store::LatestAtQuery; -use re_entity_db::external::re_query_cache::PromiseResult; +use re_entity_db::external::re_query::PromiseResult; use re_entity_db::EntityPath; use re_space_view::SpaceViewBlueprint; use re_types::blueprint::components::ViewerRecommendationHash; diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml index 32d7f1bd44a0..0b773c3de1ca 100644 --- a/examples/rust/custom_space_view/Cargo.toml +++ b/examples/rust/custom_space_view/Cargo.toml @@ -14,7 +14,7 @@ analytics = ["re_crash_handler/analytics", "re_viewer/analytics"] [dependencies] re_crash_handler = { path = "../../../crates/re_crash_handler" } -re_query2 = { path = "../../../crates/re_query2" } +re_query = { path = "../../../crates/re_query" } re_viewer = { path = "../../../crates/re_viewer", default-features = false } # We need re_sdk_comms to receive log events from and SDK: diff --git a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs index a90e12136fb1..07ef8f083bde 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs @@ -1,7 +1,7 @@ use re_viewer::external::{ egui, re_log_types::EntityPath, - re_query_cache, re_renderer, + re_query, re_renderer, re_types::{ self, components::{Color, InstanceKey}, @@ -38,13 +38,13 @@ impl re_types::Archetype for ColorArchetype { } } -impl re_query2::ToArchetype for re_query_cache::CachedLatestAtResults { +impl re_query::ToArchetype for re_query::LatestAtResults { #[inline] fn to_archetype( &self, - _resolver: &re_query2::PromiseResolver, - ) -> re_query2::PromiseResult> { - re_query2::PromiseResult::Ready(Ok(ColorArchetype)) + _resolver: &re_query::PromiseResolver, + ) -> re_query::PromiseResult> { + re_query::PromiseResult::Ready(Ok(ColorArchetype)) } } @@ -70,7 +70,7 @@ impl VisualizerSystem for InstanceColorSystem { for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { // …gather all colors and their instance ids. - let results = re_query2::latest_at( + let results = ctx.recording().query_caches().latest_at( ctx.recording_store(), &ctx.current_query(), &data_result.entity_path, diff --git a/scripts/lint.py b/scripts/lint.py index 51cf334d17db..5cf77fb98bd2 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -979,9 +979,6 @@ def lint_file(filepath: str, args: Any) -> int: def lint_crate_docs(should_ignore: Callable[[Any], bool]) -> int: """Make sure ARCHITECTURE.md talks about every single crate we have.""" - # These crates will replace existing ones and won't ever be published as-is. - tmp_crates = ["re_query2"] - crates_dir = Path("crates") architecture_md_file = Path("ARCHITECTURE.md") @@ -1002,9 +999,6 @@ def lint_crate_docs(should_ignore: Callable[[Any], bool]) -> int: if crate_name in listed_crates: del listed_crates[crate_name] - if should_ignore(crate) or crate.name in tmp_crates: - continue - if not re.search(r"\b" + crate_name + r"\b", architecture_md): print(f"{architecture_md_file}: missing documentation for crate {crate.name}") error_count += 1