refactor: rename drop_db / drop_database to drop_all_tables, expose database from connection (#2098)

If we start supporting external catalogs then "drop database" may be
misleading (and not possible). We should be more clear that this is a
utility method to drop all tables. This is also a nice chance for some
consistency cleanup as it was `drop_db` in rust, `drop_database` in
python, and non-existent in typescript.

This PR also adds a public accessor to get the database trait from a
connection.

BREAKING CHANGE: the `drop_database` / `drop_db` methods are now
deprecated.
This commit is contained in:
Weston Pace
2025-02-06 13:22:28 -08:00
committed by GitHub
parent 6bf742c759
commit 1a449fa49e
11 changed files with 102 additions and 11 deletions

View File

@@ -131,6 +131,20 @@ Return a brief description of the connection
***
### dropAllTables()
```ts
abstract dropAllTables(): Promise<void>
```
Drop all tables in the database.
#### Returns
`Promise`&lt;`void`&gt;
***
### dropTable()
```ts

View File

@@ -61,6 +61,26 @@ describe("given a connection", () => {
await expect(tbl.countRows()).resolves.toBe(1);
});
it("should be able to drop tables`", async () => {
await db.createTable("test", [{ id: 1 }, { id: 2 }]);
await db.createTable("test2", [{ id: 1 }, { id: 2 }]);
await db.createTable("test3", [{ id: 1 }, { id: 2 }]);
await expect(db.tableNames()).resolves.toEqual(["test", "test2", "test3"]);
await db.dropTable("test2");
await expect(db.tableNames()).resolves.toEqual(["test", "test3"]);
await db.dropAllTables();
await expect(db.tableNames()).resolves.toEqual([]);
// Make sure we can still create more tables after dropping all
await db.createTable("test4", [{ id: 1 }, { id: 2 }]);
});
it("should fail if creating table twice, unless overwrite is true", async () => {
let tbl = await db.createTable("test", [{ id: 1 }, { id: 2 }]);
await expect(tbl.countRows()).resolves.toBe(2);

View File

@@ -211,6 +211,11 @@ export abstract class Connection {
* @param {string} name The name of the table to drop.
*/
abstract dropTable(name: string): Promise<void>;
/**
* Drop all tables in the database.
*/
abstract dropAllTables(): Promise<void>;
}
/** @hideconstructor */
@@ -336,6 +341,10 @@ export class LocalConnection extends Connection {
async dropTable(name: string): Promise<void> {
return this.inner.dropTable(name);
}
async dropAllTables(): Promise<void> {
return this.inner.dropAllTables();
}
}
/**

View File

@@ -187,4 +187,9 @@ impl Connection {
pub async fn drop_table(&self, name: String) -> napi::Result<()> {
self.get_inner()?.drop_table(&name).await.default_error()
}
#[napi(catch_unwind)]
pub async fn drop_all_tables(&self) -> napi::Result<()> {
self.get_inner()?.drop_all_tables().await.default_error()
}
}

View File

@@ -14,6 +14,7 @@ from overrides import EnforceOverrides, override # type: ignore
from lancedb.common import data_to_reader, sanitize_uri, validate_schema
from lancedb.background_loop import LOOP
from . import __version__
from ._lancedb import connect as lancedb_connect # type: ignore
from .table import (
AsyncTable,
@@ -26,6 +27,8 @@ from .util import (
validate_table_name,
)
import deprecation
if TYPE_CHECKING:
import pyarrow as pa
from .pydantic import LanceModel
@@ -294,6 +297,12 @@ class DBConnection(EnforceOverrides):
"""
raise NotImplementedError
def drop_all_tables(self):
"""
Drop all tables from the database
"""
raise NotImplementedError
@property
def uri(self) -> str:
return self._uri
@@ -486,9 +495,19 @@ class LanceDBConnection(DBConnection):
"""
LOOP.run(self._conn.drop_table(name, ignore_missing=ignore_missing))
@override
def drop_all_tables(self):
LOOP.run(self._conn.drop_all_tables())
@deprecation.deprecated(
deprecated_in="0.15.1",
removed_in="0.17",
current_version=__version__,
details="Use drop_all_tables() instead",
)
@override
def drop_database(self):
LOOP.run(self._conn.drop_database())
LOOP.run(self._conn.drop_all_tables())
class AsyncConnection(object):
@@ -848,9 +867,19 @@ class AsyncConnection(object):
if f"Table '{name}' was not found" not in str(e):
raise e
async def drop_all_tables(self):
"""Drop all tables from the database."""
await self._inner.drop_all_tables()
@deprecation.deprecated(
deprecated_in="0.15.1",
removed_in="0.17",
current_version=__version__,
details="Use drop_all_tables() instead",
)
async def drop_database(self):
"""
Drop database
This is the same thing as dropping all the tables
"""
await self._inner.drop_db()
await self._inner.drop_all_tables()

View File

@@ -499,6 +499,10 @@ def test_delete_table(tmp_db: lancedb.DBConnection):
# if ignore_missing=True
tmp_db.drop_table("does_not_exist", ignore_missing=True)
tmp_db.drop_all_tables()
assert tmp_db.table_names() == []
@pytest.mark.asyncio
async def test_delete_table_async(tmp_db: lancedb.DBConnection):

View File

@@ -170,12 +170,11 @@ impl Connection {
})
}
pub fn drop_db(self_: PyRef<'_, Self>) -> PyResult<Bound<'_, PyAny>> {
pub fn drop_all_tables(self_: PyRef<'_, Self>) -> PyResult<Bound<'_, PyAny>> {
let inner = self_.get_inner()?.clone();
future_into_py(
self_.py(),
async move { inner.drop_db().await.infer_error() },
)
future_into_py(self_.py(), async move {
inner.drop_all_tables().await.infer_error()
})
}
}

View File

@@ -418,6 +418,11 @@ impl Connection {
self.uri.as_str()
}
/// Get access to the underlying database
pub fn database(&self) -> &Arc<dyn Database> {
&self.internal
}
/// Get the names of all tables in the database
///
/// The names will be returned in lexicographical order (ascending)
@@ -504,8 +509,14 @@ impl Connection {
/// Drop the database
///
/// This is the same as dropping all of the tables
#[deprecated(since = "0.15.1", note = "Use `drop_all_tables` instead")]
pub async fn drop_db(&self) -> Result<()> {
self.internal.drop_db().await
self.internal.drop_all_tables().await
}
/// Drops all tables in the database
pub async fn drop_all_tables(&self) -> Result<()> {
self.internal.drop_all_tables().await
}
/// Get the in-memory embedding registry.

View File

@@ -128,6 +128,6 @@ pub trait Database:
/// Drop a table in the database
async fn drop_table(&self, name: &str) -> Result<()>;
/// Drop all tables in the database
async fn drop_db(&self) -> Result<()>;
async fn drop_all_tables(&self) -> Result<()>;
fn as_any(&self) -> &dyn std::any::Any;
}

View File

@@ -529,7 +529,7 @@ impl Database for ListingDatabase {
Ok(())
}
async fn drop_db(&self) -> Result<()> {
async fn drop_all_tables(&self) -> Result<()> {
self.object_store
.remove_dir_all(self.base_path.clone())
.await?;

View File

@@ -237,7 +237,7 @@ impl<S: HttpSend> Database for RemoteDatabase<S> {
Ok(())
}
async fn drop_db(&self) -> Result<()> {
async fn drop_all_tables(&self) -> Result<()> {
Err(crate::Error::NotSupported {
message: "Dropping databases is not supported in the remote API".to_string(),
})