diff --git a/src/common/query/src/series_frame/tests.rs b/src/common/query/src/series_frame/tests.rs index aeb0fbdeb8f..e77f93e0778 100644 --- a/src/common/query/src/series_frame/tests.rs +++ b/src/common/query/src/series_frame/tests.rs @@ -2606,7 +2606,7 @@ async fn interleaved_constructors_accept_without_polling() { /// The unpack stream rejects a batch whose schema differs from the stream's declared schema, /// including drift in metadata the codec itself does not interpret and an empty batch that /// carries the drift; the reserved layout metadata is rejected as well. Since the current layout is -/// `v2`, the drift case rewrites the layout to `v1`: any value other than this revision's is refused, +/// `v1`, the drift case rewrites the layout to `v2`: any value other than this revision's is refused, /// so a stale or a future spelling cannot be decoded under the current columns. #[tokio::test] async fn unpack_rejects_unrelated_metadata_drift_and_empty_schema_changes() { @@ -2626,9 +2626,9 @@ async fn unpack_rejects_unrelated_metadata_drift_and_empty_schema_changes() { let mut unrelated = base.metadata().clone(); unrelated.insert("app.unrelated".into(), "x".into()); - // The current layout is `v2`, so a frame that still declares `v1` is the drift here. + // The current layout is `v1`, so a frame that declares `v2` is the drift here. let mut reserved = base.metadata().clone(); - reserved.insert("greptime.series.layout".into(), "v1".into()); + reserved.insert("greptime.series.layout".into(), "v2".into()); let mut renamed = base.metadata().clone(); renamed.insert("app.renamed".into(), "y".into()); let mut different_ordering = base.metadata().clone(); @@ -2696,7 +2696,7 @@ fn raw_series_ordering_metadata_fixture() { } let cases: Vec = serde_json::from_str(include_str!( - "../../../../../tests/compatibility/wire/raw_series_ordering/v2_metadata.json" + "../../../../../tests/compatibility/wire/raw_series_ordering/v1_metadata.json" )) .unwrap(); for case in cases { @@ -3286,11 +3286,11 @@ async fn unpack_reports_the_ordering_the_frame_declares() { /// Reserved layout metadata this revision does not write is rejected instead of being read as the /// current layout, so a frame cannot be decoded under a contract it did not declare. The current -/// layout is `v2`; a `v1` frame and every unknown value are refused alike. +/// layout is `v1`; a `v2` frame and every unknown value are refused alike. #[tokio::test] async fn unpack_rejects_unknown_layout_metadata() { let cases = [ - ("greptime.series.layout", "v1"), + ("greptime.series.layout", "v2"), ("greptime.series.layout", "v3"), ("greptime.series.content", "series"), ("greptime.series.time", "timestamps_v2"), diff --git a/src/datatypes/src/series/frame.rs b/src/datatypes/src/series/frame.rs index c253c262cdb..559294b4023 100644 --- a/src/datatypes/src/series/frame.rs +++ b/src/datatypes/src/series/frame.rs @@ -33,9 +33,10 @@ //! Packing accumulates bounded multi-row batches: [`SeriesFrameCursor`] walks one validated chunk //! and [`SeriesFrameBuilder`] emits rows directly as Arrow arrays once a row or estimated byte bound //! is reached. Decoding reuses one prepared -//! schema per stream through [`SeriesFrameDecoder`]. The column layout and existing metadata stay -//! on the `v2` contract. Raw frames may also declare `greptime.series.ordering=interleaved`; older -//! readers that do not recognize this ordering reject it. A key-encoded frame declares a versioned +//! schema per stream through [`SeriesFrameDecoder`]. Column layout, metadata, and wire strings stay +//! on the single `v1` contract. Raw frames may also declare `greptime.series.ordering=interleaved`; +//! older readers that do not recognize this ordering reject it. A key-encoded frame declares a +//! versioned //! [`LabelDecodeSpec`] so its labels can be decoded from the received schema alone, and an evaluated //! frame declares its [`GridSpec`] once instead of repeating timestamps. //! @@ -130,12 +131,14 @@ const RESERVED_KEYS: [&str; 9] = [ AGGREGATE_COMPONENTS, ]; -/// The only layout this revision writes and reads. +/// The layout marker every frame this engine writes carries. /// -/// A frame declaring any other value is refused instead of decoded: the sample representation of an -/// unreleased format is not worth a second decoder, and silently guessing would turn a format change -/// into wrong values. -pub const FRAME_LAYOUT_VERSION: &str = "v2"; +/// It stays at one value: the frame is the native path's internal transport and has never shipped, +/// so there is no released layout to tell apart from this one. A reader that meets another marker +/// refuses the frame instead of guessing at it - the check is what turns a stale producer into an +/// error rather than into wrong values - but the marker itself does not move when the layout +/// changes, because two binaries of one workspace are built from one revision. +pub const FRAME_LAYOUT_VERSION: &str = "v1"; /// Version of the label decode description this revision writes and reads. /// diff --git a/src/datatypes/src/series/frame/tests.rs b/src/datatypes/src/series/frame/tests.rs index 04a212c527a..d57353929a6 100644 --- a/src/datatypes/src/series/frame/tests.rs +++ b/src/datatypes/src/series/frame/tests.rs @@ -582,7 +582,7 @@ fn schema_and_key_explicit_round_trips_preserve_identity_and_bits() { .into(), ); let mut expected_key_metadata = std::collections::HashMap::new(); - expected_key_metadata.insert("greptime.series.layout".to_string(), "v2".to_string()); + expected_key_metadata.insert("greptime.series.layout".to_string(), "v1".to_string()); expected_key_metadata.insert("greptime.series.content".to_string(), "raw".to_string()); expected_key_metadata.insert("greptime.series.labels".to_string(), "key".to_string()); expected_key_metadata.insert("greptime.series.time".to_string(), "timestamps".to_string()); @@ -2061,9 +2061,9 @@ fn rejects_invalid_schema_and_metadata_and_accepts_valid_empty() { let mut metadata = valid.schema().metadata().clone(); match metadata_case { "wrong_layout" => { - // `v2` is the only layout this revision reads, so the previously unreadable `v1` - // is what a wrong layout is spelled as now. - metadata.insert("greptime.series.layout".to_string(), "v1".to_string()); + // `v1` is the only layout this revision reads, so `v2` is what a wrong layout is + // spelled as now. + metadata.insert("greptime.series.layout".to_string(), "v2".to_string()); } "wrong_labels" => { metadata.insert("greptime.series.labels".to_string(), "explicit".to_string()); @@ -3390,7 +3390,7 @@ fn cross_chunk_rows_coalesce_into_one_multirow_batch() { ["read_key", "is_last", "time", "fields"] ); for (key, value) in [ - ("greptime.series.layout", "v2"), + ("greptime.series.layout", "v1"), ("greptime.series.content", "raw"), ("greptime.series.labels", "key"), ("greptime.series.time", "timestamps"), @@ -4039,8 +4039,8 @@ fn decoder_reuses_cached_schema_and_rejects_schema_evolution() { // Reserved metadata and evolved fields are rejected, including by a zero-row batch. for (key, value) in [ - // `v2` is the layout this decoder expects, so the unreadable `v1` is the wrong one. - ("greptime.series.layout", "v1"), + // `v1` is the layout this decoder expects, so `v2` is the wrong one. + ("greptime.series.layout", "v2"), ("greptime.series.content", "evaluated"), ("greptime.series.labels", "explicit"), ("greptime.series.time", "grid"), @@ -4229,7 +4229,7 @@ fn schema_with_metadata(metadata: Vec<(String, String)>) -> Schema { /// The five metadata entries every raw v2 frame declares, with the given label mode. fn base_metadata(labels: &str) -> Vec<(String, String)> { [ - ("greptime.series.layout", "v2"), + ("greptime.series.layout", "v1"), ("greptime.series.content", "raw"), ("greptime.series.labels", labels), ("greptime.series.time", "timestamps"), @@ -4305,7 +4305,7 @@ fn raw_series_label_decode_metadata_fixture() { } let cases: Vec = serde_json::from_str(include_str!( - "../../../../../tests/compatibility/wire/raw_series_label_decode/v2_metadata.json" + "../../../../../tests/compatibility/wire/raw_series_label_decode/v1_metadata.json" )) .unwrap(); for case in cases { diff --git a/tests/compatibility/wire/raw_series_label_decode/v2_metadata.json b/tests/compatibility/wire/raw_series_label_decode/v1_metadata.json similarity index 94% rename from tests/compatibility/wire/raw_series_label_decode/v2_metadata.json rename to tests/compatibility/wire/raw_series_label_decode/v1_metadata.json index 43ded1e4bf6..3adabb36bd1 100644 --- a/tests/compatibility/wire/raw_series_label_decode/v2_metadata.json +++ b/tests/compatibility/wire/raw_series_label_decode/v1_metadata.json @@ -2,7 +2,7 @@ { "name": "key_frame_declares_dense_description", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "key", "greptime.series.time": "timestamps", @@ -14,7 +14,7 @@ { "name": "key_frame_declares_sparse_description", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "key", "greptime.series.time": "timestamps", @@ -26,7 +26,7 @@ { "name": "missing_description_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "key", "greptime.series.time": "timestamps", @@ -37,7 +37,7 @@ { "name": "unknown_version_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "key", "greptime.series.time": "timestamps", @@ -49,7 +49,7 @@ { "name": "missing_field_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "key", "greptime.series.time": "timestamps", @@ -61,7 +61,7 @@ { "name": "unknown_field_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "key", "greptime.series.time": "timestamps", @@ -73,7 +73,7 @@ { "name": "wrong_field_type_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "key", "greptime.series.time": "timestamps", @@ -85,7 +85,7 @@ { "name": "unlisted_logical_tag_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "key", "greptime.series.time": "timestamps", @@ -97,7 +97,7 @@ { "name": "explicit_frame_with_description_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "explicit", "greptime.series.time": "timestamps", @@ -109,7 +109,7 @@ { "name": "malformed_json_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "key", "greptime.series.time": "timestamps", @@ -121,7 +121,7 @@ { "name": "wrong_layout_rejected", "metadata": { - "greptime.series.layout": "v3", + "greptime.series.layout": "v2", "greptime.series.content": "raw", "greptime.series.labels": "key", "greptime.series.time": "timestamps", @@ -133,7 +133,7 @@ { "name": "unregistered_reserved_metadata_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "key", "greptime.series.time": "timestamps", @@ -146,7 +146,7 @@ { "name": "evaluated_with_timestamps_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "evaluated", "greptime.series.labels": "explicit", "greptime.series.time": "timestamps", @@ -158,7 +158,7 @@ { "name": "evaluated_with_key_labels_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "evaluated", "greptime.series.labels": "key", "greptime.series.time": "grid_spans", @@ -171,7 +171,7 @@ { "name": "raw_with_grid_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "explicit", "greptime.series.time": "timestamps", diff --git a/tests/compatibility/wire/raw_series_ordering/README.md b/tests/compatibility/wire/raw_series_ordering/README.md index ce54838048a..a80c7f8f2da 100644 --- a/tests/compatibility/wire/raw_series_ordering/README.md +++ b/tests/compatibility/wire/raw_series_ordering/README.md @@ -1,7 +1,7 @@ # Raw-series ordering schema metadata compatibility -`v2_metadata.json` is a hand-authored, frozen set of Arrow schema metadata maps -for the v2 series frame. It records the established layout/content/labels/time +`v1_metadata.json` is a hand-authored, frozen set of Arrow schema metadata maps +for the series frame, whose layout marker is the single `v1` this engine writes. It records the established layout/content/labels/time metadata and mandatory ordering entry, for raw frames and for evaluated ones. The Rust unit test parses these literal maps through `series_frame_ordering` and through `SeriesFrameDeclaration::parse`; the fixture is not produced by the @@ -17,7 +17,7 @@ cargo nextest run -p common-query -E 'test(series_frame)' The fixture proves that missing ordering metadata and unknown values are rejected, the two original values decode, and that a whole declaration is accepted or -refused consistently with its layout and content: a `v3` layout, an unregistered +refused consistently with its layout and content: a `v2` layout, an unregistered `greptime.series.*` key, a raw frame that declares a grid, and any content/time or content/labels contradiction are refusals. Evaluated declarations use explicit `contiguous` ordering; streaming round trips for evaluated frames are covered by diff --git a/tests/compatibility/wire/raw_series_ordering/v2_metadata.json b/tests/compatibility/wire/raw_series_ordering/v1_metadata.json similarity index 91% rename from tests/compatibility/wire/raw_series_ordering/v2_metadata.json rename to tests/compatibility/wire/raw_series_ordering/v1_metadata.json index 4b01c12091d..fced5bbbcb9 100644 --- a/tests/compatibility/wire/raw_series_ordering/v2_metadata.json +++ b/tests/compatibility/wire/raw_series_ordering/v1_metadata.json @@ -2,7 +2,7 @@ { "name": "missing_ordering_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "explicit", "greptime.series.time": "timestamps" @@ -13,7 +13,7 @@ { "name": "known_contiguous", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "explicit", "greptime.series.time": "timestamps", @@ -25,7 +25,7 @@ { "name": "known_read_key_then_time", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "explicit", "greptime.series.time": "timestamps", @@ -37,7 +37,7 @@ { "name": "unknown_ordering_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "explicit", "greptime.series.time": "timestamps", @@ -49,7 +49,7 @@ { "name": "evaluated_contiguous", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "evaluated", "greptime.series.labels": "explicit", "greptime.series.time": "grid_spans", @@ -62,7 +62,7 @@ { "name": "evaluated_read_key_then_time_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "evaluated", "greptime.series.labels": "explicit", "greptime.series.time": "grid_spans", @@ -75,7 +75,7 @@ { "name": "wrong_layout_rejected", "metadata": { - "greptime.series.layout": "v3", + "greptime.series.layout": "v2", "greptime.series.content": "raw", "greptime.series.labels": "explicit", "greptime.series.time": "timestamps", @@ -87,7 +87,7 @@ { "name": "unregistered_reserved_metadata_rejected", "metadata": { - "greptime.series.layout": "v2", + "greptime.series.layout": "v1", "greptime.series.content": "raw", "greptime.series.labels": "explicit", "greptime.series.time": "timestamps",