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