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