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