Skip to main content

lance_namespace/
namespace.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright The Lance Authors
3
4//! Lance Namespace base interface and implementations.
5
6use async_trait::async_trait;
7use bytes::Bytes;
8use lance_core::{Error, Result};
9use snafu::Location;
10
11use lance_namespace_reqwest_client::models::{
12    AlterTableAddColumnsRequest, AlterTableAddColumnsResponse, AlterTableAlterColumnsRequest,
13    AlterTableAlterColumnsResponse, AlterTableDropColumnsRequest, AlterTableDropColumnsResponse,
14    AlterTransactionRequest, AlterTransactionResponse, AnalyzeTableQueryPlanRequest,
15    CountTableRowsRequest, CreateEmptyTableRequest, CreateEmptyTableResponse,
16    CreateNamespaceRequest, CreateNamespaceResponse, CreateTableIndexRequest,
17    CreateTableIndexResponse, CreateTableRequest, CreateTableResponse,
18    CreateTableScalarIndexResponse, CreateTableTagRequest, CreateTableTagResponse,
19    DeclareTableRequest, DeclareTableResponse, DeleteFromTableRequest, DeleteFromTableResponse,
20    DeleteTableTagRequest, DeleteTableTagResponse, DeregisterTableRequest, DeregisterTableResponse,
21    DescribeNamespaceRequest, DescribeNamespaceResponse, DescribeTableIndexStatsRequest,
22    DescribeTableIndexStatsResponse, DescribeTableRequest, DescribeTableResponse,
23    DescribeTransactionRequest, DescribeTransactionResponse, DropNamespaceRequest,
24    DropNamespaceResponse, DropTableIndexRequest, DropTableIndexResponse, DropTableRequest,
25    DropTableResponse, ExplainTableQueryPlanRequest, GetTableStatsRequest, GetTableStatsResponse,
26    GetTableTagVersionRequest, GetTableTagVersionResponse, InsertIntoTableRequest,
27    InsertIntoTableResponse, ListNamespacesRequest, ListNamespacesResponse,
28    ListTableIndicesRequest, ListTableIndicesResponse, ListTableTagsRequest, ListTableTagsResponse,
29    ListTableVersionsRequest, ListTableVersionsResponse, ListTablesRequest, ListTablesResponse,
30    MergeInsertIntoTableRequest, MergeInsertIntoTableResponse, NamespaceExistsRequest,
31    QueryTableRequest, RegisterTableRequest, RegisterTableResponse, RenameTableRequest,
32    RenameTableResponse, RestoreTableRequest, RestoreTableResponse, TableExistsRequest,
33    UpdateTableRequest, UpdateTableResponse, UpdateTableSchemaMetadataRequest,
34    UpdateTableSchemaMetadataResponse, UpdateTableTagRequest, UpdateTableTagResponse,
35};
36
37/// Base trait for Lance Namespace implementations.
38///
39/// This trait defines the interface that all Lance namespace implementations
40/// must provide. Each method corresponds to a specific operation on namespaces
41/// or tables.
42///
43/// # Error Handling
44///
45/// All operations may return the following common errors (via [`crate::NamespaceError`]):
46///
47/// - [`crate::ErrorCode::Unsupported`] - Operation not supported by this backend
48/// - [`crate::ErrorCode::InvalidInput`] - Invalid request parameters
49/// - [`crate::ErrorCode::PermissionDenied`] - Insufficient permissions
50/// - [`crate::ErrorCode::Unauthenticated`] - Invalid credentials
51/// - [`crate::ErrorCode::ServiceUnavailable`] - Service temporarily unavailable
52/// - [`crate::ErrorCode::Internal`] - Unexpected internal error
53///
54/// See individual method documentation for operation-specific errors.
55#[async_trait]
56pub trait LanceNamespace: Send + Sync + std::fmt::Debug {
57    /// List namespaces.
58    ///
59    /// # Errors
60    ///
61    /// Returns [`crate::ErrorCode::NamespaceNotFound`] if the parent namespace does not exist.
62    async fn list_namespaces(
63        &self,
64        _request: ListNamespacesRequest,
65    ) -> Result<ListNamespacesResponse> {
66        Err(Error::NotSupported {
67            source: "list_namespaces not implemented".into(),
68            location: Location::new(file!(), line!(), column!()),
69        })
70    }
71
72    /// Describe a namespace.
73    ///
74    /// # Errors
75    ///
76    /// Returns [`crate::ErrorCode::NamespaceNotFound`] if the namespace does not exist.
77    async fn describe_namespace(
78        &self,
79        _request: DescribeNamespaceRequest,
80    ) -> Result<DescribeNamespaceResponse> {
81        Err(Error::NotSupported {
82            source: "describe_namespace not implemented".into(),
83            location: Location::new(file!(), line!(), column!()),
84        })
85    }
86
87    /// Create a new namespace.
88    ///
89    /// # Errors
90    ///
91    /// Returns [`crate::ErrorCode::NamespaceAlreadyExists`] if a namespace with the same name already exists.
92    async fn create_namespace(
93        &self,
94        _request: CreateNamespaceRequest,
95    ) -> Result<CreateNamespaceResponse> {
96        Err(Error::NotSupported {
97            source: "create_namespace not implemented".into(),
98            location: Location::new(file!(), line!(), column!()),
99        })
100    }
101
102    /// Drop a namespace.
103    ///
104    /// # Errors
105    ///
106    /// - [`crate::ErrorCode::NamespaceNotFound`] if the namespace does not exist.
107    /// - [`crate::ErrorCode::NamespaceNotEmpty`] if the namespace contains tables or child namespaces.
108    async fn drop_namespace(
109        &self,
110        _request: DropNamespaceRequest,
111    ) -> Result<DropNamespaceResponse> {
112        Err(Error::NotSupported {
113            source: "drop_namespace not implemented".into(),
114            location: Location::new(file!(), line!(), column!()),
115        })
116    }
117
118    /// Check if a namespace exists.
119    ///
120    /// # Errors
121    ///
122    /// Returns [`crate::ErrorCode::NamespaceNotFound`] if the namespace does not exist.
123    async fn namespace_exists(&self, _request: NamespaceExistsRequest) -> Result<()> {
124        Err(Error::NotSupported {
125            source: "namespace_exists not implemented".into(),
126            location: Location::new(file!(), line!(), column!()),
127        })
128    }
129
130    /// List tables in a namespace.
131    async fn list_tables(&self, _request: ListTablesRequest) -> Result<ListTablesResponse> {
132        Err(Error::NotSupported {
133            source: "list_tables not implemented".into(),
134            location: Location::new(file!(), line!(), column!()),
135        })
136    }
137
138    /// Describe a table.
139    async fn describe_table(
140        &self,
141        _request: DescribeTableRequest,
142    ) -> Result<DescribeTableResponse> {
143        Err(Error::NotSupported {
144            source: "describe_table not implemented".into(),
145            location: Location::new(file!(), line!(), column!()),
146        })
147    }
148
149    /// Register a table.
150    async fn register_table(
151        &self,
152        _request: RegisterTableRequest,
153    ) -> Result<RegisterTableResponse> {
154        Err(Error::NotSupported {
155            source: "register_table not implemented".into(),
156            location: Location::new(file!(), line!(), column!()),
157        })
158    }
159
160    /// Check if a table exists.
161    async fn table_exists(&self, _request: TableExistsRequest) -> Result<()> {
162        Err(Error::NotSupported {
163            source: "table_exists not implemented".into(),
164            location: Location::new(file!(), line!(), column!()),
165        })
166    }
167
168    /// Drop a table.
169    async fn drop_table(&self, _request: DropTableRequest) -> Result<DropTableResponse> {
170        Err(Error::NotSupported {
171            source: "drop_table not implemented".into(),
172            location: Location::new(file!(), line!(), column!()),
173        })
174    }
175
176    /// Deregister a table.
177    async fn deregister_table(
178        &self,
179        _request: DeregisterTableRequest,
180    ) -> Result<DeregisterTableResponse> {
181        Err(Error::NotSupported {
182            source: "deregister_table not implemented".into(),
183            location: Location::new(file!(), line!(), column!()),
184        })
185    }
186
187    /// Count rows in a table.
188    async fn count_table_rows(&self, _request: CountTableRowsRequest) -> Result<i64> {
189        Err(Error::NotSupported {
190            source: "count_table_rows not implemented".into(),
191            location: Location::new(file!(), line!(), column!()),
192        })
193    }
194
195    /// Create a new table with data from Arrow IPC stream.
196    async fn create_table(
197        &self,
198        _request: CreateTableRequest,
199        _request_data: Bytes,
200    ) -> Result<CreateTableResponse> {
201        Err(Error::NotSupported {
202            source: "create_table not implemented".into(),
203            location: Location::new(file!(), line!(), column!()),
204        })
205    }
206
207    /// Declare a table (metadata only operation).
208    async fn declare_table(&self, _request: DeclareTableRequest) -> Result<DeclareTableResponse> {
209        Err(Error::NotSupported {
210            source: "declare_table not implemented".into(),
211            location: Location::new(file!(), line!(), column!()),
212        })
213    }
214
215    /// Create an empty table (metadata only operation).
216    ///
217    /// # Deprecated
218    ///
219    /// Use [`declare_table`](Self::declare_table) instead. Support will be removed in 3.0.0.
220    #[deprecated(
221        since = "2.0.0",
222        note = "Use declare_table instead. Support will be removed in 3.0.0."
223    )]
224    async fn create_empty_table(
225        &self,
226        _request: CreateEmptyTableRequest,
227    ) -> Result<CreateEmptyTableResponse> {
228        Err(Error::NotSupported {
229            source: "create_empty_table not implemented".into(),
230            location: Location::new(file!(), line!(), column!()),
231        })
232    }
233
234    /// Insert data into a table.
235    async fn insert_into_table(
236        &self,
237        _request: InsertIntoTableRequest,
238        _request_data: Bytes,
239    ) -> Result<InsertIntoTableResponse> {
240        Err(Error::NotSupported {
241            source: "insert_into_table not implemented".into(),
242            location: Location::new(file!(), line!(), column!()),
243        })
244    }
245
246    /// Merge insert data into a table.
247    async fn merge_insert_into_table(
248        &self,
249        _request: MergeInsertIntoTableRequest,
250        _request_data: Bytes,
251    ) -> Result<MergeInsertIntoTableResponse> {
252        Err(Error::NotSupported {
253            source: "merge_insert_into_table not implemented".into(),
254            location: Location::new(file!(), line!(), column!()),
255        })
256    }
257
258    /// Update a table.
259    async fn update_table(&self, _request: UpdateTableRequest) -> Result<UpdateTableResponse> {
260        Err(Error::NotSupported {
261            source: "update_table not implemented".into(),
262            location: Location::new(file!(), line!(), column!()),
263        })
264    }
265
266    /// Delete from a table.
267    async fn delete_from_table(
268        &self,
269        _request: DeleteFromTableRequest,
270    ) -> Result<DeleteFromTableResponse> {
271        Err(Error::NotSupported {
272            source: "delete_from_table not implemented".into(),
273            location: Location::new(file!(), line!(), column!()),
274        })
275    }
276
277    /// Query a table.
278    async fn query_table(&self, _request: QueryTableRequest) -> Result<Bytes> {
279        Err(Error::NotSupported {
280            source: "query_table not implemented".into(),
281            location: Location::new(file!(), line!(), column!()),
282        })
283    }
284
285    /// Create a table index.
286    async fn create_table_index(
287        &self,
288        _request: CreateTableIndexRequest,
289    ) -> Result<CreateTableIndexResponse> {
290        Err(Error::NotSupported {
291            source: "create_table_index not implemented".into(),
292            location: Location::new(file!(), line!(), column!()),
293        })
294    }
295
296    /// List table indices.
297    async fn list_table_indices(
298        &self,
299        _request: ListTableIndicesRequest,
300    ) -> Result<ListTableIndicesResponse> {
301        Err(Error::NotSupported {
302            source: "list_table_indices not implemented".into(),
303            location: Location::new(file!(), line!(), column!()),
304        })
305    }
306
307    /// Describe table index statistics.
308    async fn describe_table_index_stats(
309        &self,
310        _request: DescribeTableIndexStatsRequest,
311    ) -> Result<DescribeTableIndexStatsResponse> {
312        Err(Error::NotSupported {
313            source: "describe_table_index_stats not implemented".into(),
314            location: Location::new(file!(), line!(), column!()),
315        })
316    }
317
318    /// Describe a transaction.
319    async fn describe_transaction(
320        &self,
321        _request: DescribeTransactionRequest,
322    ) -> Result<DescribeTransactionResponse> {
323        Err(Error::NotSupported {
324            source: "describe_transaction not implemented".into(),
325            location: Location::new(file!(), line!(), column!()),
326        })
327    }
328
329    /// Alter a transaction.
330    async fn alter_transaction(
331        &self,
332        _request: AlterTransactionRequest,
333    ) -> Result<AlterTransactionResponse> {
334        Err(Error::NotSupported {
335            source: "alter_transaction not implemented".into(),
336            location: Location::new(file!(), line!(), column!()),
337        })
338    }
339
340    /// Create a scalar index on a table.
341    async fn create_table_scalar_index(
342        &self,
343        _request: CreateTableIndexRequest,
344    ) -> Result<CreateTableScalarIndexResponse> {
345        Err(Error::NotSupported {
346            source: "create_table_scalar_index not implemented".into(),
347            location: Location::new(file!(), line!(), column!()),
348        })
349    }
350
351    /// Drop a table index.
352    async fn drop_table_index(
353        &self,
354        _request: DropTableIndexRequest,
355    ) -> Result<DropTableIndexResponse> {
356        Err(Error::NotSupported {
357            source: "drop_table_index not implemented".into(),
358            location: Location::new(file!(), line!(), column!()),
359        })
360    }
361
362    /// List all tables across all namespaces.
363    async fn list_all_tables(&self, _request: ListTablesRequest) -> Result<ListTablesResponse> {
364        Err(Error::NotSupported {
365            source: "list_all_tables not implemented".into(),
366            location: Location::new(file!(), line!(), column!()),
367        })
368    }
369
370    /// Restore a table to a specific version.
371    async fn restore_table(&self, _request: RestoreTableRequest) -> Result<RestoreTableResponse> {
372        Err(Error::NotSupported {
373            source: "restore_table not implemented".into(),
374            location: Location::new(file!(), line!(), column!()),
375        })
376    }
377
378    /// Rename a table.
379    async fn rename_table(&self, _request: RenameTableRequest) -> Result<RenameTableResponse> {
380        Err(Error::NotSupported {
381            source: "rename_table not implemented".into(),
382            location: Location::new(file!(), line!(), column!()),
383        })
384    }
385
386    /// List all versions of a table.
387    async fn list_table_versions(
388        &self,
389        _request: ListTableVersionsRequest,
390    ) -> Result<ListTableVersionsResponse> {
391        Err(Error::NotSupported {
392            source: "list_table_versions not implemented".into(),
393            location: Location::new(file!(), line!(), column!()),
394        })
395    }
396
397    /// Update table schema metadata.
398    async fn update_table_schema_metadata(
399        &self,
400        _request: UpdateTableSchemaMetadataRequest,
401    ) -> Result<UpdateTableSchemaMetadataResponse> {
402        Err(Error::NotSupported {
403            source: "update_table_schema_metadata not implemented".into(),
404            location: Location::new(file!(), line!(), column!()),
405        })
406    }
407
408    /// Get table statistics.
409    async fn get_table_stats(
410        &self,
411        _request: GetTableStatsRequest,
412    ) -> Result<GetTableStatsResponse> {
413        Err(Error::NotSupported {
414            source: "get_table_stats not implemented".into(),
415            location: Location::new(file!(), line!(), column!()),
416        })
417    }
418
419    /// Explain a table query plan.
420    async fn explain_table_query_plan(
421        &self,
422        _request: ExplainTableQueryPlanRequest,
423    ) -> Result<String> {
424        Err(Error::NotSupported {
425            source: "explain_table_query_plan not implemented".into(),
426            location: Location::new(file!(), line!(), column!()),
427        })
428    }
429
430    /// Analyze a table query plan.
431    async fn analyze_table_query_plan(
432        &self,
433        _request: AnalyzeTableQueryPlanRequest,
434    ) -> Result<String> {
435        Err(Error::NotSupported {
436            source: "analyze_table_query_plan not implemented".into(),
437            location: Location::new(file!(), line!(), column!()),
438        })
439    }
440
441    /// Add columns to a table.
442    async fn alter_table_add_columns(
443        &self,
444        _request: AlterTableAddColumnsRequest,
445    ) -> Result<AlterTableAddColumnsResponse> {
446        Err(Error::NotSupported {
447            source: "alter_table_add_columns not implemented".into(),
448            location: Location::new(file!(), line!(), column!()),
449        })
450    }
451
452    /// Alter columns in a table.
453    async fn alter_table_alter_columns(
454        &self,
455        _request: AlterTableAlterColumnsRequest,
456    ) -> Result<AlterTableAlterColumnsResponse> {
457        Err(Error::NotSupported {
458            source: "alter_table_alter_columns not implemented".into(),
459            location: Location::new(file!(), line!(), column!()),
460        })
461    }
462
463    /// Drop columns from a table.
464    async fn alter_table_drop_columns(
465        &self,
466        _request: AlterTableDropColumnsRequest,
467    ) -> Result<AlterTableDropColumnsResponse> {
468        Err(Error::NotSupported {
469            source: "alter_table_drop_columns not implemented".into(),
470            location: Location::new(file!(), line!(), column!()),
471        })
472    }
473
474    /// List all tags for a table.
475    async fn list_table_tags(
476        &self,
477        _request: ListTableTagsRequest,
478    ) -> Result<ListTableTagsResponse> {
479        Err(Error::NotSupported {
480            source: "list_table_tags not implemented".into(),
481            location: Location::new(file!(), line!(), column!()),
482        })
483    }
484
485    /// Get the version for a specific tag.
486    async fn get_table_tag_version(
487        &self,
488        _request: GetTableTagVersionRequest,
489    ) -> Result<GetTableTagVersionResponse> {
490        Err(Error::NotSupported {
491            source: "get_table_tag_version not implemented".into(),
492            location: Location::new(file!(), line!(), column!()),
493        })
494    }
495
496    /// Create a tag for a table.
497    async fn create_table_tag(
498        &self,
499        _request: CreateTableTagRequest,
500    ) -> Result<CreateTableTagResponse> {
501        Err(Error::NotSupported {
502            source: "create_table_tag not implemented".into(),
503            location: Location::new(file!(), line!(), column!()),
504        })
505    }
506
507    /// Delete a tag from a table.
508    async fn delete_table_tag(
509        &self,
510        _request: DeleteTableTagRequest,
511    ) -> Result<DeleteTableTagResponse> {
512        Err(Error::NotSupported {
513            source: "delete_table_tag not implemented".into(),
514            location: Location::new(file!(), line!(), column!()),
515        })
516    }
517
518    /// Update a tag for a table.
519    async fn update_table_tag(
520        &self,
521        _request: UpdateTableTagRequest,
522    ) -> Result<UpdateTableTagResponse> {
523        Err(Error::NotSupported {
524            source: "update_table_tag not implemented".into(),
525            location: Location::new(file!(), line!(), column!()),
526        })
527    }
528
529    /// Return a human-readable unique identifier for this namespace instance.
530    ///
531    /// This is used for equality comparison and hashing when the namespace is
532    /// used as part of a storage options provider. Two namespace instances with
533    /// the same ID are considered equal and will share cached resources.
534    ///
535    /// The ID should be human-readable for debugging and logging purposes.
536    /// For example:
537    /// - REST namespace: `"rest(endpoint=https://api.example.com)"`
538    /// - Directory namespace: `"dir(root=/path/to/data)"`
539    ///
540    /// Implementations should include all configuration that uniquely identifies
541    /// the namespace to provide semantic equality.
542    fn namespace_id(&self) -> String;
543}