lance_table/transaction/prepare.rs
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright The Lance Authors
3
4//! What a commit attempt settles about the index list before the manifest
5//! is built.
6//!
7//! The commit layer decides index validity; the manifest builder assembles.
8//! Once per attempt, against the manifest current at that attempt,
9//! [`Transaction::prepare_indices`](crate::transaction::Transaction::prepare_indices)
10//! reads the index list as it is, keeps that original list untouched, and
11//! derives a prepared list on which an in-place column rewrite has already
12//! withdrawn or pruned the coverage it invalidates (on a table with a tagged
13//! fragment reuse history along the lineage, on any other table by fragment
14//! id). The builder then applies the operation to the prepared list and
15//! publishes only the final list; the original list is what MemWAL coverage
16//! is compared against. Both lists are in-memory metadata of one attempt:
17//! nothing is copied on disk and a retry prepares afresh from the list it
18//! reads then.
19
20use crate::format::IndexMetadata;
21use crate::transaction::TaggedRewriteAssembly;
22use std::sync::Arc;
23
24/// What the commit path settled about the fragment reuse entry for one
25/// attempt. In-memory only, like the rewrite intent it carries.
26#[derive(Debug, Clone, Default)]
27#[non_exhaustive]
28pub enum FragReuseUpdate {
29 /// Nothing was prepared for the entry. A tagged entry arriving on a
30 /// `Rewrite`, or a `CreateIndex` touching a tagged entry, is refused:
31 /// without the commit path's derivation such a shape is a pre-assembled
32 /// snapshot that may splice away records a concurrent writer appended.
33 #[default]
34 None,
35 /// A `Rewrite` on a tagged history: the entry the commit path assembled
36 /// for THIS manifest, merging the records the operation's entry adds
37 /// onto the current entry and validating them.
38 Rewrite(Arc<TaggedRewriteAssembly>),
39 /// A trim of the tagged entry derived by the reuse index cleanup against
40 /// the current entry at commit time.
41 Trim,
42}
43
44/// The index lists of one commit attempt: the list as read from the
45/// manifest current at the attempt, the prepared list the builder starts
46/// from, and what was settled about the fragment reuse entry.
47///
48/// Only [`Transaction::prepare_indices`](crate::transaction::Transaction::prepare_indices)
49/// builds one, so a value always went through the tagged-table write gate
50/// and the unified withdrawal step; the manifest it was prepared against is
51/// recorded so the builder refuses a result carried over to another attempt.
52#[derive(Debug, Clone)]
53pub struct PreparedIndices {
54 manifest_version: Option<u64>,
55 original: Vec<IndexMetadata>,
56 prepared: Vec<IndexMetadata>,
57 frag_reuse: FragReuseUpdate,
58}
59
60impl PreparedIndices {
61 pub(crate) fn new(
62 manifest_version: Option<u64>,
63 original: Vec<IndexMetadata>,
64 prepared: Vec<IndexMetadata>,
65 frag_reuse: FragReuseUpdate,
66 ) -> Self {
67 Self {
68 manifest_version,
69 original,
70 prepared,
71 frag_reuse,
72 }
73 }
74
75 /// The version of the manifest the lists were prepared against; `None`
76 /// when the dataset is being created.
77 pub fn manifest_version(&self) -> Option<u64> {
78 self.manifest_version
79 }
80
81 /// The index list as read from the current manifest, never mutated.
82 pub fn original(&self) -> &[IndexMetadata] {
83 &self.original
84 }
85
86 /// The original list with the in-place rewrite step applied: the list
87 /// the manifest builder starts from.
88 pub fn prepared(&self) -> &[IndexMetadata] {
89 &self.prepared
90 }
91
92 /// What the commit path settled about the fragment reuse entry.
93 pub fn frag_reuse_update(&self) -> &FragReuseUpdate {
94 &self.frag_reuse
95 }
96
97 pub(crate) fn into_parts(self) -> (Vec<IndexMetadata>, Vec<IndexMetadata>, FragReuseUpdate) {
98 (self.original, self.prepared, self.frag_reuse)
99 }
100}