feat: drop_index() remote implementation (#2093)

Support drop_index operation in remote table.
This commit is contained in:
Ryan Green
2025-02-05 10:06:19 -03:30
committed by GitHub
parent 16851389ea
commit ef3093bc23
10 changed files with 109 additions and 6 deletions

View File

@@ -38,6 +38,13 @@ components:
required: true
schema:
type: string
index_name:
name: index_name
in: path
description: name of the index
required: true
schema:
type: string
responses:
invalid_request:
description: Invalid request
@@ -485,3 +492,22 @@ paths:
$ref: "#/components/responses/unauthorized"
"404":
$ref: "#/components/responses/not_found"
/v1/table/{name}/index/{index_name}/drop/:
post:
description: Drop an index from the table
tags:
- Tables
summary: Drop an index from the table
operationId: dropIndex
parameters:
- $ref: "#/components/parameters/table_name"
- $ref: "#/components/parameters/index_name"
responses:
"200":
description: Index successfully dropped
"400":
$ref: "#/components/responses/invalid_request"
"401":
$ref: "#/components/responses/unauthorized"
"404":
$ref: "#/components/responses/not_found"

View File

@@ -47,7 +47,8 @@ const {
tableSchema,
tableAddColumns,
tableAlterColumns,
tableDropColumns
tableDropColumns,
tableDropIndex
// eslint-disable-next-line @typescript-eslint/no-var-requires
} = require("../native.js");
@@ -604,6 +605,13 @@ export interface Table<T = number[]> {
*/
dropColumns(columnNames: string[]): Promise<void>
/**
* Drop an index from the table
*
* @param indexName The name of the index to drop
*/
dropIndex(indexName: string): Promise<void>
/**
* Instrument the behavior of this Table with middleware.
*
@@ -1206,6 +1214,10 @@ export class LocalTable<T = number[]> implements Table<T> {
return tableDropColumns.call(this._tbl, columnNames);
}
async dropIndex(indexName: string): Promise<void> {
return tableDropIndex.call(this._tbl, indexName);
}
withMiddleware(middleware: HttpMiddleware): Table<T> {
return this;
}

View File

@@ -471,6 +471,18 @@ export class RemoteTable<T = number[]> implements Table<T> {
)
}
}
async dropIndex (index_name: string): Promise<void> {
const res = await this._client.post(
`/v1/table/${encodeURIComponent(this._name)}/index/${encodeURIComponent(index_name)}/drop/`
)
if (res.status !== 200) {
throw new Error(
`Server Error, status: ${res.status}, ` +
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`message: ${res.statusText}: ${await res.body()}`
)
}
}
async countRows (filter?: string): Promise<number> {
const result = await this._client.post(`/v1/table/${encodeURIComponent(this._name)}/count_rows/`, {

View File

@@ -894,6 +894,27 @@ describe("LanceDB client", function () {
expect(stats.distanceType).to.equal("l2");
expect(stats.numIndices).to.equal(1);
}).timeout(50_000);
// not yet implemented
// it("can drop index", async function () {
// const uri = await createTestDB(32, 300);
// const con = await lancedb.connect(uri);
// const table = await con.openTable("vectors");
// await table.createIndex({
// type: "ivf_pq",
// column: "vector",
// num_partitions: 2,
// max_iters: 2,
// num_sub_vectors: 2
// });
//
// const indices = await table.listIndices();
// expect(indices).to.have.lengthOf(1);
// expect(indices[0].name).to.equal("vector_idx");
//
// await table.dropIndex("vector_idx");
// expect(await table.listIndices()).to.have.lengthOf(0);
// }).timeout(50_000);
});
describe("when using a custom embedding function", function () {

View File

@@ -526,6 +526,9 @@ class RemoteTable(Table):
def drop_columns(self, columns: Iterable[str]):
return LOOP.run(self._table.drop_columns(columns))
def drop_index(self, index_name: str):
return LOOP.run(self._table.drop_index(index_name))
def uses_v2_manifest_paths(self) -> bool:
raise NotImplementedError(
"uses_v2_manifest_paths() is not supported on the LanceDB Cloud"

View File

@@ -255,6 +255,9 @@ def test_table_create_indices():
)
)
request.wfile.write(payload.encode())
elif "/drop/" in request.path:
request.send_response(200)
request.end_headers()
else:
request.send_response(404)
request.end_headers()
@@ -266,6 +269,9 @@ def test_table_create_indices():
table.create_scalar_index("id")
table.create_fts_index("text")
table.create_scalar_index("vector")
table.drop_index("vector_idx")
table.drop_index("id_idx")
table.drop_index("text_idx")
@contextlib.contextmanager

View File

@@ -169,5 +169,6 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> {
cx.export_function("tableAddColumns", JsTable::js_add_columns)?;
cx.export_function("tableAlterColumns", JsTable::js_alter_columns)?;
cx.export_function("tableDropColumns", JsTable::js_drop_columns)?;
cx.export_function("tableDropIndex", JsTable::js_drop_index)?;
Ok(())
}

View File

@@ -638,4 +638,8 @@ impl JsTable {
Ok(promise)
}
pub(crate) fn js_drop_index(_cx: FunctionContext) -> JsResult<JsPromise> {
todo!("not implemented")
}
}

View File

@@ -15,6 +15,8 @@ pub enum Error {
InvalidInput { message: String },
#[snafu(display("Table '{name}' was not found"))]
TableNotFound { name: String },
#[snafu(display("Index '{name}' was not found"))]
IndexNotFound { name: String },
#[snafu(display("Embedding function '{name}' was not found. : {reason}"))]
EmbeddingFunctionNotFound { name: String, reason: String },

View File

@@ -820,11 +820,14 @@ impl<S: HttpSend> TableInternal for RemoteTable<S> {
Ok(Some(stats))
}
/// Not yet supported on LanceDB Cloud.
async fn drop_index(&self, _name: &str) -> Result<()> {
Err(Error::NotSupported {
message: "Drop index is not yet supported on LanceDB Cloud.".into(),
})
async fn drop_index(&self, index_name: &str) -> Result<()> {
let request = self.client.post(&format!(
"/v1/table/{}/index/{}/drop/",
self.name, index_name
));
let (request_id, response) = self.client.send(request, true).await?;
self.check_table_response(&request_id, response).await?;
Ok(())
}
async fn table_definition(&self) -> Result<TableDefinition> {
@@ -2022,4 +2025,17 @@ mod tests {
table.drop_columns(&["a", "b"]).await.unwrap();
}
#[tokio::test]
async fn test_drop_index() {
let table = Table::new_with_handler("my_table", |request| {
assert_eq!(request.method(), "POST");
assert_eq!(
request.url().path(),
"/v1/table/my_table/index/my_index/drop/"
);
http::Response::builder().status(200).body("{}").unwrap()
});
table.drop_index("my_index").await.unwrap();
}
}