lance_encoding/
version.rs1use std::str::FromStr;
5
6use lance_arrow::DataTypeExt;
7use lance_core::datatypes::Field;
8use lance_core::deepsize::{Context, DeepSizeOf};
9use lance_core::{Error, Result};
10
11pub const LEGACY_FORMAT_VERSION: &str = "0.1";
12pub const V2_FORMAT_2_0: &str = "2.0";
13pub const V2_FORMAT_2_1: &str = "2.1";
14pub const V2_FORMAT_2_2: &str = "2.2";
15pub const V2_FORMAT_2_3: &str = "2.3";
16
17#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Ord, PartialOrd, strum::EnumIter)]
19pub enum LanceFileVersion {
20 Legacy,
31 V2_0,
32 #[default]
33 V2_1,
34 Stable,
36 V2_2,
37 Next,
39 V2_3,
40}
41
42impl DeepSizeOf for LanceFileVersion {
43 fn deep_size_of_children(&self, _context: &mut Context) -> usize {
44 0
45 }
46}
47
48impl LanceFileVersion {
49 pub fn resolve(&self) -> Self {
51 match self {
52 Self::Stable => Self::default(),
53 Self::Next => Self::V2_3,
54 _ => *self,
55 }
56 }
57
58 pub fn is_unstable(&self) -> bool {
59 self >= &Self::Next
60 }
61
62 pub fn try_from_major_minor(major: u32, minor: u32) -> Result<Self> {
63 match (major, minor) {
64 (0, 0) => Ok(Self::Legacy),
65 (0, 1) => Ok(Self::Legacy),
66 (0, 2) => Ok(Self::Legacy),
67 (0, 3) => Ok(Self::V2_0),
68 (2, 0) => Ok(Self::V2_0),
69 (2, 1) => Ok(Self::V2_1),
70 (2, 2) => Ok(Self::V2_2),
71 (2, 3) => Ok(Self::V2_3),
72 _ => Err(Error::invalid_input_source(
73 format!("Unknown Lance storage version: {}.{}", major, minor).into(),
74 )),
75 }
76 }
77
78 pub fn to_numbers(&self) -> (u32, u32) {
79 match self {
80 Self::Legacy => (0, 2),
81 Self::V2_0 => (2, 0),
82 Self::V2_1 => (2, 1),
83 Self::V2_2 => (2, 2),
84 Self::V2_3 => (2, 3),
85 Self::Stable => self.resolve().to_numbers(),
86 Self::Next => self.resolve().to_numbers(),
87 }
88 }
89
90 pub fn iter_non_legacy() -> impl Iterator<Item = Self> {
91 use strum::IntoEnumIterator;
92
93 Self::iter().filter(|&v| v != Self::Stable && v != Self::Next && v != Self::Legacy)
94 }
95
96 pub fn support_add_sub_column(&self) -> bool {
97 self > &Self::V2_1
98 }
99
100 pub fn support_remove_sub_column(&self, field: &Field) -> bool {
101 if self <= &Self::V2_1 {
102 field.data_type().is_struct()
103 } else {
104 field.data_type().is_nested()
105 }
106 }
107}
108
109impl std::fmt::Display for LanceFileVersion {
110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111 write!(
112 f,
113 "{}",
114 match self {
115 Self::Legacy => LEGACY_FORMAT_VERSION,
116 Self::V2_0 => V2_FORMAT_2_0,
117 Self::V2_1 => V2_FORMAT_2_1,
118 Self::V2_2 => V2_FORMAT_2_2,
119 Self::V2_3 => V2_FORMAT_2_3,
120 Self::Stable => "stable",
121 Self::Next => "next",
122 }
123 )
124 }
125}
126
127impl FromStr for LanceFileVersion {
128 type Err = Error;
129
130 fn from_str(value: &str) -> Result<Self> {
131 match value.to_lowercase().as_str() {
132 LEGACY_FORMAT_VERSION => Ok(Self::Legacy),
133 V2_FORMAT_2_0 => Ok(Self::V2_0),
134 V2_FORMAT_2_1 => Ok(Self::V2_1),
135 V2_FORMAT_2_2 => Ok(Self::V2_2),
136 V2_FORMAT_2_3 => Ok(Self::V2_3),
137 "stable" => Ok(Self::Stable),
138 "legacy" => Ok(Self::Legacy),
139 "next" => Ok(Self::Next),
140 "0.3" => Ok(Self::V2_0),
142 _ => Err(Error::invalid_input_source(
143 format!("Unknown Lance storage version: {}", value).into(),
144 )),
145 }
146 }
147}