Skip to content

SQL functions ​

Functions live in the postvec schema, so every call is qualified: postvec.enable(...), postvec.search(...). Signatures, option values and defaults are in the SQL reference.

Where to start ​

SituationFirst callThen
A text column with no vectorsenable()index, then search
A populated vector(N) columnadopt()search on the stored space
Vectors from a model you no longer calladopt() with that modelsearch a retired space: each query is converted into the stored space
Long source documentsenable(chunking => 'recursive')search returns one row per document plus the winning chunk
A stored model to replacemigrate()migration_finalize() swaps the column
An existing pgai or pg_vectorize pipelineComing from pgaimap the vectorizer to enable() or adopt()

Lifecycle ​

CallEffect
enable(relation, column_name, model, ...)Adds the shadow vector column, installs enqueue triggers and queues the existing rows
adopt(relation, column_name, vector_column, model, ...)Registers a populated vector column and leaves the stored bytes alone
set_format(relation, column_name, format)Replaces the embedding template and refreshes the entry in one transaction
disable(relation, column_name, ...)Removes the objects the entry owns and marks its registry row state = 'disabled'
uninstall(...)Tears down every entry and marks each registry row state = 'disabled'; tables and vectors stay unless the destructive flags are set

A disabled row stays in postvec.registry. A later enable() or adopt() on that column clears it and registers a new row.

CallEffect
search(relation, column_name, query, ...)Hybrid search in one call. Full-text and vector results fused with reciprocal rank fusion
search_with_vector(relation, column_name, query_vector, query_text, ...)The same search when the application already holds the query vector
create_vector_index(relation, column_name)Builds the ANN index for the entry. index_mode can also ask the worker to build it
refresh_lexical_stats(relation, column_name)Rebuilds the BM25 corpus statistics now

Filters (filter =>), the semantic/lexical mix (semantic_weight), the candidate pool (candidates) and chunk collapse are documented in Search, Filters and BM25.

Migration ​

CallEffect
migrate(relation, column_name, new_model, strategy => ...)Starts a migration: convert translates stored vectors, reembed re-runs the source text
migration_status(migration_id)State, progress, the route in use and the index statement to run next
migration_finalize(migration_id)Swaps in the migrated column; a fresh ANN index finishes in a second call
migration_abort(migration_id)Stops the migration and keeps the original column
convert(embedding, source_model, target_model)One-shot vector conversion, callable on its own

Operations ​

CallEffect
status()Per-entry health: queue depth, dead jobs, readiness, chunking, index and lexical state
stats()Worker and queue counters
retry_dead(relation, column_name, dead_ids)Re-drives dead-lettered rows as fresh deduplicated jobs
refresh_models()Re-reads the model inventory from the inference host
embed(input, model)One-shot embedding, outside the queue
version() / build_info()Extension version and build details

Grants ​

enable, adopt, disable, set_format, migrate, create_vector_index, retry_dead and refresh_lexical_stats need the table owner or a superuser. uninstall() and start_worker() are superuser only. search(), search_with_vector(), status(), stats() and version() are executable by PUBLIC. embed, convert and refresh_models are revoked from PUBLIC.

Non-owner DML on an enabled table needs USAGE on schema postvec and a column-scoped INSERT (registry_id, pk_value) on postvec.jobs.

Where inference runs ​

Inference runs inside the PostgreSQL process by default. The SQL above is the same when the work runs in postvec-server: a separate process, multi-threaded on the same VM, or a CPU and GPU fleet on the network. A database that cannot load the extension uses the server for managed PostgreSQL.