fix: preserve all function revisions through SQL history (#4786)

`list_functions()` promises every published immutable revision. Request
`SHOW FUNCTIONS HISTORY` so the SQL server's latest-only default does
not hide older revisions, and preserve the server's numeric revision
ordering when constructing page cursors (`1`, `2`, `10`).

```python
[(fn.name, fn.version) for fn in db.list_functions(page_limit=2)]
# [("embed", "1"), ("embed", "2"), ("embed", "10")]
```

```sql
SHOW FUNCTIONS; -- latest visible revision per name
SHOW FUNCTIONS HISTORY WITH (limit = 3, include_definition = true);
SHOW FUNCTIONS HISTORY WITH (after_name = 'embed', after_version = '2', limit = 3);
```

Each listing page uses the existing SQL query and polling transport; the
continuation token stores the last returned name/revision and remains
bound to its database and namespace. Function mutations keep their
query-backed job handles: `Job.id` is the query's ID and `job_type` is
`query`, so waiting observes that same SQL execution. No registry job or
second query ID is added.

Update the SQL and Python documentation for exact-revision drops:
sibling revisions and grants survive, and only the last visible
revision's removal releases the name and schedules object cleanup.
Extend the existing Flight SQL regression to paginate revisions `1`,
`2`, and `10` and verify the explicit history statement. Formatting and
static Python checks pass; local builds and tests were intentionally not
run.
This commit is contained in:
Jack Ye
2026-11-02 01:15:39 +08:00
committed by GitHub
parent cbc24fa84f
commit eeb244fa57
6 changed files with 92 additions and 52 deletions
+8 -6
View File
@@ -564,13 +564,15 @@ itself is: as source, snapshotted at registration.
## Drop it {#drop}
`db.drop_function(name, version=...)` drops the function's name and the object
it is bound to; `version` must be a version that exists. It returns `False` if
the name was already gone. Deleting the object's content can finish after the
call returns, as a [background job](/maintenance/background-jobs).
`db.drop_function(name, version=...)` removes only that published revision from
lookup and listing, preserving other revisions and their grants. It returns
`False` for a repeated drop or a name that is already gone. A revision never
published under an existing name is an error. The last visible revision's drop
releases the name and schedules object cleanup, which can finish after the call
returns as a [background job](/maintenance/background-jobs).
`drop_function_async` returns `(dropped, job)`, where `job` is a query-backed
handle. Waiting confirms catalog
removal; physical cleanup can continue afterward.
handle. Waiting confirms the revision's catalog removal; physical cleanup can
continue afterward.
A deployment refuses the drop unless it also allows changes to a function's
lifecycle, which is a separate setting, off by default even where Functions are
+13 -7
View File
@@ -107,12 +107,15 @@ from it.
```sql
SHOW FUNCTIONS
SHOW FUNCTIONS IN "analytics" WITH (name = 'embed', limit = 100)
SHOW FUNCTIONS WITH (after_name = 'embed', after_version = '1', limit = 100)
SHOW FUNCTIONS HISTORY IN "analytics" WITH (name = 'embed', limit = 100)
SHOW FUNCTIONS HISTORY WITH (after_name = 'embed', after_version = '1', limit = 100)
```
Rows are ordered lexicographically by name and version. `after_name` and
`after_version` must be supplied together for keyset pagination. `limit` bounds
`SHOW FUNCTIONS` returns the highest published numeric revision for each name.
Add `HISTORY` to list every published revision, as Python's `list_functions()`
does. Rows are ordered by name and numeric revision, so `2` comes before `10`.
`after_name` and `after_version` must be supplied together for keyset pagination.
`limit` bounds
the response; `include_definition = false` omits the optional definition JSON.
## DROP FUNCTION {#drop}
@@ -122,9 +125,12 @@ DROP FUNCTION embed WITH (version = '1')
DROP FUNCTION IF EXISTS embed WITH (version = '1')
```
`version` must identify an existing revision. DROP releases the function name
and its object binding; physical cleanup continues separately. The result
reports `dropped` or `not_found`. `IF EXISTS` allows a missing name.
DROP removes only the requested revision from lookup and listing. Other
published revisions and their grants remain available. Dropping the last visible
revision releases the name and object binding; physical cleanup continues
separately. The result reports `dropped` or `not_found`. `IF EXISTS` allows a
missing name or a repeated drop of a previously published revision. A revision
that was never published under an existing name is an error.
All function object commands retain shared results even when general query-result
copying is disabled, so asynchronous polling can resume on another query node.