1use std::{any::Any, sync::Arc};
13
14use crate::frag_reuse::FRAG_REUSE_INDEX_NAME;
15use crate::mem_wal::MEM_WAL_INDEX_NAME;
16use async_trait::async_trait;
17use deepsize::DeepSizeOf;
18use lance_core::{Error, Result};
19use roaring::RoaringBitmap;
20use serde::{Deserialize, Serialize};
21use snafu::location;
22use std::convert::TryFrom;
23
24pub mod frag_reuse;
25pub mod mem_wal;
26pub mod metrics;
27pub mod optimize;
28pub mod prefilter;
29pub mod scalar;
30pub mod traits;
31pub mod vector;
32
33pub use crate::traits::*;
34
35pub const INDEX_FILE_NAME: &str = "index.idx";
36pub const INDEX_AUXILIARY_FILE_NAME: &str = "auxiliary.idx";
41pub const INDEX_METADATA_SCHEMA_KEY: &str = "lance:index";
42
43pub mod pb {
44 #![allow(clippy::use_self)]
45 include!(concat!(env!("OUT_DIR"), "/lance.index.pb.rs"));
46}
47
48#[async_trait]
51pub trait Index: Send + Sync + DeepSizeOf {
52 fn as_any(&self) -> &dyn Any;
54
55 fn as_index(self: Arc<Self>) -> Arc<dyn Index>;
57
58 fn as_vector_index(self: Arc<Self>) -> Result<Arc<dyn vector::VectorIndex>>;
60
61 fn statistics(&self) -> Result<serde_json::Value>;
63
64 async fn prewarm(&self) -> Result<()>;
68
69 fn index_type(&self) -> IndexType;
71
72 async fn calculate_included_frags(&self) -> Result<RoaringBitmap>;
77}
78
79#[derive(Debug, PartialEq, Eq, Copy, Hash, Clone, DeepSizeOf)]
81pub enum IndexType {
82 Scalar = 0, BTree = 1, Bitmap = 2, LabelList = 3, Inverted = 4, NGram = 5, FragmentReuse = 6,
96
97 MemWal = 7,
98
99 ZoneMap = 8, Vector = 100, IvfFlat = 101,
105 IvfSq = 102,
106 IvfPq = 103,
107 IvfHnswSq = 104,
108 IvfHnswPq = 105,
109 IvfHnswFlat = 106,
110}
111
112impl std::fmt::Display for IndexType {
113 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
114 match self {
115 Self::Scalar | Self::BTree => write!(f, "BTree"),
116 Self::Bitmap => write!(f, "Bitmap"),
117 Self::LabelList => write!(f, "LabelList"),
118 Self::Inverted => write!(f, "Inverted"),
119 Self::NGram => write!(f, "NGram"),
120 Self::FragmentReuse => write!(f, "FragmentReuse"),
121 Self::MemWal => write!(f, "MemWal"),
122 Self::ZoneMap => write!(f, "ZoneMap"),
123 Self::Vector | Self::IvfPq => write!(f, "IVF_PQ"),
124 Self::IvfFlat => write!(f, "IVF_FLAT"),
125 Self::IvfSq => write!(f, "IVF_SQ"),
126 Self::IvfHnswSq => write!(f, "IVF_HNSW_SQ"),
127 Self::IvfHnswPq => write!(f, "IVF_HNSW_PQ"),
128 Self::IvfHnswFlat => write!(f, "IVF_HNSW_FLAT"),
129 }
130 }
131}
132
133impl TryFrom<i32> for IndexType {
134 type Error = Error;
135
136 fn try_from(value: i32) -> Result<Self> {
137 match value {
138 v if v == Self::Scalar as i32 => Ok(Self::Scalar),
139 v if v == Self::BTree as i32 => Ok(Self::BTree),
140 v if v == Self::Bitmap as i32 => Ok(Self::Bitmap),
141 v if v == Self::LabelList as i32 => Ok(Self::LabelList),
142 v if v == Self::NGram as i32 => Ok(Self::NGram),
143 v if v == Self::Inverted as i32 => Ok(Self::Inverted),
144 v if v == Self::FragmentReuse as i32 => Ok(Self::FragmentReuse),
145 v if v == Self::MemWal as i32 => Ok(Self::MemWal),
146 v if v == Self::ZoneMap as i32 => Ok(Self::ZoneMap),
147 v if v == Self::Vector as i32 => Ok(Self::Vector),
148 v if v == Self::IvfFlat as i32 => Ok(Self::IvfFlat),
149 v if v == Self::IvfSq as i32 => Ok(Self::IvfSq),
150 v if v == Self::IvfPq as i32 => Ok(Self::IvfPq),
151 v if v == Self::IvfHnswSq as i32 => Ok(Self::IvfHnswSq),
152 v if v == Self::IvfHnswPq as i32 => Ok(Self::IvfHnswPq),
153 v if v == Self::IvfHnswFlat as i32 => Ok(Self::IvfHnswFlat),
154 _ => Err(Error::InvalidInput {
155 source: format!("the input value {} is not a valid IndexType", value).into(),
156 location: location!(),
157 }),
158 }
159 }
160}
161
162impl IndexType {
163 pub fn is_scalar(&self) -> bool {
164 matches!(
165 self,
166 Self::Scalar
167 | Self::BTree
168 | Self::Bitmap
169 | Self::LabelList
170 | Self::Inverted
171 | Self::NGram
172 | Self::ZoneMap
173 )
174 }
175
176 pub fn is_vector(&self) -> bool {
177 matches!(
178 self,
179 Self::Vector
180 | Self::IvfPq
181 | Self::IvfHnswSq
182 | Self::IvfHnswPq
183 | Self::IvfHnswFlat
184 | Self::IvfFlat
185 | Self::IvfSq
186 )
187 }
188
189 pub fn is_system(&self) -> bool {
190 matches!(self, Self::FragmentReuse | Self::MemWal)
191 }
192
193 pub fn version(&self) -> i32 {
199 match self {
200 Self::Scalar => 0,
201 Self::BTree => 0,
202 Self::Bitmap => 0,
203 Self::LabelList => 0,
204 Self::Inverted => 0,
205 Self::NGram => 0,
206 Self::FragmentReuse => 0,
207 Self::MemWal => 0,
208 Self::ZoneMap => 0,
209
210 Self::Vector
213 | Self::IvfFlat
214 | Self::IvfSq
215 | Self::IvfPq
216 | Self::IvfHnswSq
217 | Self::IvfHnswPq
218 | Self::IvfHnswFlat => 1,
219 }
220 }
221}
222
223pub trait IndexParams: Send + Sync {
224 fn as_any(&self) -> &dyn Any;
225
226 fn index_type(&self) -> IndexType;
227
228 fn index_name(&self) -> &str;
229}
230
231#[derive(Serialize, Deserialize, Debug)]
232pub struct IndexMetadata {
233 #[serde(rename = "type")]
234 pub index_type: String,
235 pub distance_type: String,
236}
237
238pub fn is_system_index(index_meta: &lance_table::format::Index) -> bool {
239 index_meta.name == FRAG_REUSE_INDEX_NAME || index_meta.name == MEM_WAL_INDEX_NAME
240}
241
242pub fn infer_system_index_type(index_meta: &lance_table::format::Index) -> Option<IndexType> {
243 if index_meta.name == FRAG_REUSE_INDEX_NAME {
244 Some(IndexType::FragmentReuse)
245 } else if index_meta.name == MEM_WAL_INDEX_NAME {
246 Some(IndexType::MemWal)
247 } else {
248 None
249 }
250}