Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions java/lance-jni/src/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,23 @@ pub extern "system" fn Java_org_lance_namespace_RestNamespace_declareTableNative
.into_raw()
}

#[no_mangle]
pub extern "system" fn Java_org_lance_namespace_RestNamespace_renameTableNative(
mut env: JNIEnv,
_obj: JObject,
handle: jlong,
request_json: JString,
) -> jstring {
ok_or_throw_with_return!(
env,
call_rest_namespace_method(&mut env, handle, request_json, |ns, req| {
RT.block_on(ns.inner.rename_table(req))
}),
std::ptr::null_mut()
)
.into_raw()
}

#[no_mangle]
pub extern "system" fn Java_org_lance_namespace_RestNamespace_insertIntoTableNative(
mut env: JNIEnv,
Expand Down
10 changes: 10 additions & 0 deletions java/src/main/java/org/lance/namespace/RestNamespace.java
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,14 @@ public DeclareTableResponse declareTable(DeclareTableRequest request) {
return fromJson(responseJson, DeclareTableResponse.class);
}

@Override
public RenameTableResponse renameTable(RenameTableRequest request) {
ensureInitialized();
String requestJson = toJson(request);
String responseJson = renameTableNative(nativeRestNamespaceHandle, requestJson);
return fromJson(responseJson, RenameTableResponse.class);
}

@Override
public InsertIntoTableResponse insertIntoTable(
InsertIntoTableRequest request, byte[] requestData) {
Expand Down Expand Up @@ -397,6 +405,8 @@ private native long createNativeWithProvider(

private native String declareTableNative(long handle, String requestJson);

private native String renameTableNative(long handle, String requestJson);

private native String insertIntoTableNative(long handle, String requestJson, byte[] requestData);

private native String mergeInsertIntoTableNative(
Expand Down
36 changes: 36 additions & 0 deletions java/src/test/java/org/lance/namespace/RestNamespaceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -325,4 +325,40 @@ void testCreateEmptyTable() {
assertNotNull(createResp);
assertNotNull(createResp.getLocation());
}

@Test
void testRenameTable() throws Exception {
// Create parent namespace
CreateNamespaceRequest createNsReq =
new CreateNamespaceRequest().id(Arrays.asList("workspace"));
namespace.createNamespace(createNsReq);

// Create a table
byte[] tableData = createTestTableData();
CreateTableRequest createReq =
new CreateTableRequest().id(Arrays.asList("workspace", "test_table"));
namespace.createTable(createReq, tableData);

// TODO: underlying dir namespace doesn't support rename yet...

// // Rename the table
// RenameTableRequest renameReq =
// new RenameTableRequest()
// .id(Arrays.asList("workspace", "test_table"))
// .newNamespaceId(Arrays.asList("workspace"))
// .newTableName("test_table_renamed");

// RenameTableResponse renameRes = namespace.renameTable(renameReq);
// assertNotNull(renameRes);

// // Verify table with old name no longer exists
// TableExistsRequest oldExistsReq =
// new TableExistsRequest().id(Arrays.asList("workspace", "test_table"));
// assertThrows(RuntimeException.class, () -> namespace.tableExists(oldExistsReq));

// // Verify table with new name exists
// TableExistsRequest existsReq =
// new TableExistsRequest().id(Arrays.asList("workspace", "test_table_renamed"));
// assertDoesNotThrow(() -> namespace.tableExists(existsReq));
}
}
6 changes: 6 additions & 0 deletions python/python/lance/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
NamespaceExistsRequest,
RegisterTableRequest,
RegisterTableResponse,
RenameTableRequest,
RenameTableResponse,
TableExistsRequest,
)

Expand Down Expand Up @@ -536,6 +538,10 @@ def declare_table(self, request: DeclareTableRequest) -> DeclareTableResponse:
response_dict = self._inner.declare_table(request.model_dump())
return DeclareTableResponse.from_dict(response_dict)

def rename_table(self, request: RenameTableRequest) -> RenameTableResponse:
response_dict = self._inner.rename_table(request.model_dump())
return RenameTableResponse.from_dict(response_dict)


class RestAdapter:
"""REST adapter server that creates a namespace backend and exposes it via REST.
Expand Down
33 changes: 33 additions & 0 deletions python/python/tests/test_namespace_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,39 @@ def test_register_table_rejects_path_traversal(self, rest_namespace):
rest_namespace.register_table(register_req)
assert "Path traversal is not allowed" in str(exc_info.value)

def test_rename_table(self, rest_namespace):
"""Test renaming a table."""
# Create parent namespace
create_ns_req = CreateNamespaceRequest(id=["workspace"])
rest_namespace.create_namespace(create_ns_req)

# Create table
table_data = create_test_data()
ipc_data = table_to_ipc_bytes(table_data)
create_req = CreateTableRequest(id=["workspace", "test_table"])
rest_namespace.create_table(create_req, ipc_data)

# TODO: underlying dir namespace doesn't support rename yet...

# # Rename the table
# rename_req = RenameTableRequest(
# id=["workspace", "test_table"],
# new_namespace_id=["workspace"],
# new_table_name="test_table_renamed",
# )

# response = rest_namespace.rename_table(rename_req)
# assert response is not None

# # Verify table with old name no longer exists
# exists_req = TableExistsRequest(id=["workspace", "test_table"])
# with pytest.raises(Exception):
# rest_namespace.table_exists(exists_req)

# # Verify table with new name exists
# exists_req = TableExistsRequest(id=["workspace", "test_table_renamed"])
# rest_namespace.table_exists(exists_req)


class TestChildNamespaceOperations:
"""Tests for operations in child namespaces - mirrors DirectoryNamespace tests."""
Expand Down
12 changes: 12 additions & 0 deletions python/src/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,18 @@ impl PyRestNamespace {
.infer_error()?;
Ok(pythonize(py, &response)?.into())
}

fn rename_table<'py>(
&self,
py: Python<'py>,
request: &Bound<'_, PyAny>,
) -> PyResult<Bound<'py, PyAny>> {
let request = depythonize(request)?;
let response = crate::rt()
.block_on(Some(py), self.inner.rename_table(request))?
.infer_error()?;
Ok(pythonize(py, &response)?.into())
}
}

/// Python wrapper for REST adapter server
Expand Down
Loading