feat: author generated column refresh jobs

This commit is contained in:
Xuanwo
2026-08-12 20:01:09 +08:00
parent 4843445a7e
commit d7d25cd5ef
5 changed files with 1074 additions and 0 deletions
+1
View File
@@ -372,6 +372,7 @@ class Table:
async def _generated_column_status(
self, column_name: str
) -> Literal["complete", "incomplete"]: ...
async def _refresh_generated_column(self, column_name: str) -> Job: ...
async def list_versions(self) -> List[Dict[str, Any]]: ...
async def version(self) -> int: ...
async def checkout(self, version: Union[int, str]): ...
+9
View File
@@ -593,6 +593,15 @@ class RemoteTable(Table):
"""
return LOOP.run(self._table.generated_column_status(column_name))
def refresh_generated_column(self, column_name: str) -> Job:
"""Refresh values for an existing generated column.
Returns a :class:`~lancedb.job.Job` for the refresh operation. Acceptance
of the Job does not publish new values; callers must wait and re-read
the table to observe refreshed results.
"""
return Job(LOOP.run(self._table.refresh_generated_column(column_name)))
def _is_legacy_create_index_call(
self,
first_arg: str,
+28
View File
@@ -1027,6 +1027,15 @@ class Table(ABC):
"""
raise NotImplementedError
def refresh_generated_column(self, column_name: str) -> Job:
"""Refresh values for an existing generated column.
Returns a :class:`~lancedb.job.Job` for the refresh operation. Acceptance
of the Job does not publish new values; callers must wait and re-read
the table to observe refreshed results.
"""
raise NotImplementedError
def drop_index(self, name: str) -> None:
"""
Drop an index from the table.
@@ -2888,6 +2897,15 @@ class LanceTable(Table):
"""
return LOOP.run(self._table.generated_column_status(column_name))
def refresh_generated_column(self, column_name: str) -> Job:
"""Refresh values for an existing generated column.
Returns a :class:`~lancedb.job.Job` for the refresh operation. Acceptance
of the Job does not publish new values; callers must wait and re-read
the table to observe refreshed results.
"""
return Job(LOOP.run(self._table.refresh_generated_column(column_name)))
def _is_legacy_create_index_call(
self,
first_arg: str,
@@ -5127,6 +5145,16 @@ class AsyncTable:
"""
return await self._inner._generated_column_status(column_name)
async def refresh_generated_column(self, column_name: str) -> AsyncJob:
"""Refresh values for an existing generated column.
Returns an :class:`~lancedb.job.AsyncJob` for the refresh operation.
Acceptance of the Job does not publish new values; callers must wait
and re-read the table to observe refreshed results.
"""
job = await self._inner._refresh_generated_column(column_name)
return AsyncJob(job)
async def drop_index(self, name: str) -> None:
"""
Drop an index from the table.
File diff suppressed because it is too large Load Diff
+35
View File
@@ -992,6 +992,41 @@ impl Table {
})
}
/// Hidden bridge: load exact definition, resolve Function by ID, submit refresh.
///
/// Private native path for Python ``table.refresh_generated_column``. Rejects
/// an empty ``column_name`` before reading the table handle. Does not expose
/// source version, Function, field IDs, epochs, specs, or request envelope.
#[doc(hidden)]
pub fn _refresh_generated_column<'a>(
self_: PyRef<'a, Self>,
column_name: String,
) -> PyResult<Bound<'a, PyAny>> {
if column_name.is_empty() {
return Err(PyValueError::new_err("column_name must be non-empty"));
}
let inner = self_.inner_ref()?.clone();
future_into_py(self_.py(), async move {
let (source_table_version, definition) = inner
.generated_column_definition_snapshot(column_name)
.await
.infer_error()?;
let function_id = definition.function_call().function_id().clone();
let function = inner
.resolve_function_for_generated_column(&function_id)
.await
.infer_error()?;
let spec =
lancedb::function::RefreshGeneratedColumnJobSpec::try_new(&function, definition)
.infer_error()?;
let job = inner
.submit_refresh_generated_column(source_table_version, spec)
.await
.infer_error()?;
Ok(crate::job::Job::new(job))
})
}
pub fn drop_index(self_: PyRef<'_, Self>, index_name: String) -> PyResult<Bound<'_, PyAny>> {
let inner = self_.inner_ref()?.clone();
future_into_py(self_.py(), async move {