> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# VEF Coverage Compared to PostgreSQL

> This page is a comparison of the VillageSQL Extension Framework with PostgreSQL's extension framework, showing which interfaces and hooks VEF supports today and where the remaining work is tracked.

The VillageSQL Extension Framework (VEF) gives an extension access to the inner
workings of the database in a defined way. PostgreSQL has the most mature
extension framework of any open-source database, so this page uses it as a point
of reference to give you a sense of VEF's current and planned capabilities.

You should read this page as a snapshot, rather than the finished state. VEF
changes with each release. Matching PostgreSQL's hook capabilities exactly is not
the goal. MySQL and PostgreSQL are different databases and the needs of their
users are often different too.

## Capabilities specific to VillageSQL

Some of what VEF offers has nothing to compare against in the tables below,
either because MySQL is built differently or because VillageSQL extension
authors needed something PostgreSQL does not give its own extensions.

* **Keyring access** — `vsql::preview::keyring` lets an extension read secrets
  from the server's keyring.
* **Extension-private file storage** — `vsql::preview::storage` gives an
  extension a managed place on disk. PostgreSQL extensions manage their own
  files, without a server-side API for it.
* **Alternative protocol handlers** —
  [#299](https://github.com/villagesql/villagesql-server/issues/299) would let
  an extension serve clients over something other than the MySQL wire protocol.

Two further capabilities exist because of how MySQL is built. Binary log write
and flush observation
([#297](https://github.com/villagesql/villagesql-server/issues/297)) and
replication channel observation
([#341](https://github.com/villagesql/villagesql-server/issues/341)) both read
MySQL's binary log and its multi-source replication channels. PostgreSQL covers
comparable ground through logical decoding on the WAL and its subscription
machinery, which is a different design serving a similar purpose.

## How to read the tables

| Status          | Meaning                                                                                               |
| --------------- | ----------------------------------------------------------------------------------------------------- |
| **Available**   | You can do this in an extension today. The row names the capability or SDK function that provides it. |
| **Partial**     | Part of this works today. The row, or the note under the table, says what is missing.                 |
| **In progress** | Some of the work has landed. The linked issues carry the rest.                                        |
| **Planned**     | Not available yet. The linked issue tracks the work.                                                  |

Every row that is not marked **Available** links the GitHub issue where that
work is tracked and discussed.

Anything marked **Available** through a preview capability needs
`vsql_allow_preview_extensions = ON` — see
[Preview Capabilities](/docs/mysql-8.4/dev/preview-capabilities).

## C++ and Rust

You can write a VillageSQL extension in either C++ or Rust. VEF is the
server-side capability and each SDK is a binding over it; the Rust bindings are
newer, so a few capabilities are reachable from C++ only for now.

| Capability                    | C++ SDK | Rust SDK                                                                       |
| ----------------------------- | ------- | ------------------------------------------------------------------------------ |
| Scalar functions (VDFs)       | Yes     | Yes                                                                            |
| Custom types                  | Yes     | Yes                                                                            |
| System and status variables   | Yes     | Yes                                                                            |
| Background workers            | Yes     | Yes                                                                            |
| Keyring access                | Yes     | Yes                                                                            |
| Aggregate functions           | Yes     | Not yet — [rust-sdk#37](https://github.com/villagesql/vsql-rust-sdk/issues/37) |
| Load and unload callbacks     | Yes     | Not yet — [rust-sdk#13](https://github.com/villagesql/vsql-rust-sdk/issues/13) |
| Running SQL from an extension | Yes     | Not yet — [rust-sdk#37](https://github.com/villagesql/vsql-rust-sdk/issues/37) |
| Statement completion events   | Yes     | Not yet — [rust-sdk#37](https://github.com/villagesql/vsql-rust-sdk/issues/37) |
| Authentication methods        | Yes     | Not yet — [rust-sdk#37](https://github.com/villagesql/vsql-rust-sdk/issues/37) |
| Extension-private storage     | Yes     | Not yet — [rust-sdk#37](https://github.com/villagesql/vsql-rust-sdk/issues/37) |

## Pluggable interfaces

These interfaces, rather than the hooks further down, are what the best-known
PostgreSQL extensions are built on. They are also the part of the framework VEF
covers most completely, so start here.

| PostgreSQL interface                     | What it does                                                                   | VillageSQL                                                                                                                                                                                                                                                                                   |
| ---------------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `_PG_init`, `_PG_fini`                   | Run setup when the module loads, and teardown when it unloads                  | **Available** — `on_init()` and `on_deinit()` on the extension builder                                                                                                                                                                                                                       |
| Custom data types and operators          | Register a new base type with its own storage and comparison behaviour         | **Available** — see [Custom Types](/docs/mysql-8.4/dev/custom-types)                                                                                                                                                                                                                              |
| Aggregate functions                      | Register a user-defined aggregate                                              | **Available** — `make_aggregate_func`, see [Development Guide](/docs/mysql-8.4/dev/development)                                                                                                                                                                                                   |
| Custom configuration variables           | Define settings the operator can change at runtime, and counters they can read | **Available** — `vsql::sys_var` for settings, `vsql::status_var` for counters                                                                                                                                                                                                                |
| Background workers                       | Run a long-lived process inside the server, with database access               | **Available** — `vsql::preview::thread_worker`                                                                                                                                                                                                                                               |
| SPI (running SQL from inside the server) | Execute SQL from extension code                                                | **Partial** — `vsql::preview::sql_query`, with the limits noted below                                                                                                                                                                                                                        |
| Set-returning functions                  | Return a result set from a function                                            | Planned — [#549](https://github.com/villagesql/villagesql-server/issues/549)                                                                                                                                                                                                                 |
| Procedures written in C                  | Expose an operation as `CALL`, not as a scalar function                        | Planned — [#596](https://github.com/villagesql/villagesql-server/issues/596)                                                                                                                                                                                                                 |
| Index access methods                     | Register a whole index type, with build, maintenance, and search               | In progress — [#264](https://github.com/villagesql/villagesql-server/issues/264), [#265](https://github.com/villagesql/villagesql-server/issues/265), [#266](https://github.com/villagesql/villagesql-server/issues/266), [#268](https://github.com/villagesql/villagesql-server/issues/268) |
| Custom scan providers                    | Add extension-defined nodes to the executor                                    | Planned — [#276](https://github.com/villagesql/villagesql-server/issues/276)                                                                                                                                                                                                                 |
| Table access methods                     | Replace row storage, visibility, and vacuum behaviour                          | Planned — [#290](https://github.com/villagesql/villagesql-server/issues/290), [#291](https://github.com/villagesql/villagesql-server/issues/291), [#292](https://github.com/villagesql/villagesql-server/issues/292)                                                                         |
| Foreign data wrappers                    | Expose an external system as a table, with predicate pushdown and writes       | Planned — [#277](https://github.com/villagesql/villagesql-server/issues/277), [#278](https://github.com/villagesql/villagesql-server/issues/278), [#279](https://github.com/villagesql/villagesql-server/issues/279), [#280](https://github.com/villagesql/villagesql-server/issues/280)     |
| Logical decoding output plugins          | Consume a stream of row changes                                                | Planned — [#283](https://github.com/villagesql/villagesql-server/issues/283), [#284](https://github.com/villagesql/villagesql-server/issues/284), [#285](https://github.com/villagesql/villagesql-server/issues/285)                                                                         |
| System views for extension state         | Publish extension state as a queryable table                                   | Planned — [#271](https://github.com/villagesql/villagesql-server/issues/271)                                                                                                                                                                                                                 |
| Procedural languages                     | Add a language runtime for stored routines                                     | Planned — [#342](https://github.com/villagesql/villagesql-server/issues/342)                                                                                                                                                                                                                 |

`on_init()` and `on_deinit()` run inside the extension with no access to the
server, unlike `_PG_init`. They suit local setup such as choosing
CPU-specific function pointers. Setup that has to talk to the server belongs in
a capability's populate step instead.

`vsql::preview::sql_query` has three limits that affect any extension built
around SPI. Statements take no bind parameters, so values have to be escaped by
hand ([#627](https://github.com/villagesql/villagesql-server/issues/627)). An
extension gets a single session rather than concurrent ones
([#626](https://github.com/villagesql/villagesql-server/issues/626)). And it
cannot be called from inside a VDF
([#597](https://github.com/villagesql/villagesql-server/issues/597)).

## Hook variables

A hook is a point where the server hands control to an extension mid-statement,
letting it read or change what the server is about to do. PostgreSQL declares a
fixed set of them as global function pointers; the tables below cover all of
them, grouped by the stage of query processing each one fires in.

### Parsing and DDL

| PostgreSQL hook                                | What it does                                                                   | VillageSQL                                                                   |
| ---------------------------------------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------- |
| `post_parse_analyze_hook`                      | Inspect or rewrite a statement after parse analysis                            | Planned — [#701](https://github.com/villagesql/villagesql-server/issues/701) |
| `ProcessUtility_hook`                          | Intercept, block, or redirect DDL and other utility statements before they run | Planned — [#272](https://github.com/villagesql/villagesql-server/issues/272) |
| `object_access_hook`, `object_access_hook_str` | Be notified when a catalog object is created, altered, dropped, or accessed    | Planned — [#270](https://github.com/villagesql/villagesql-server/issues/270) |

### Planner

| PostgreSQL hook                                   | What it does                                                     | VillageSQL                                                                   |
| ------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `planner_hook`                                    | Wrap or replace the planner for a statement                      | Planned — [#275](https://github.com/villagesql/villagesql-server/issues/275) |
| `set_rel_pathlist_hook`                           | Add or remove candidate scan paths for one table                 | Planned — [#275](https://github.com/villagesql/villagesql-server/issues/275) |
| `set_join_pathlist_hook`                          | Add or remove candidate join paths                               | Planned — [#275](https://github.com/villagesql/villagesql-server/issues/275) |
| `join_search_hook`                                | Replace the join-order search itself                             | Planned — [#275](https://github.com/villagesql/villagesql-server/issues/275) |
| `create_upper_paths_hook`                         | Add paths for post-scan stages such as grouping and ordering     | Planned — [#275](https://github.com/villagesql/villagesql-server/issues/275) |
| `get_relation_info_hook`                          | Adjust the relation and index metadata the planner sees          | Planned — [#268](https://github.com/villagesql/villagesql-server/issues/268) |
| `get_relation_stats_hook`, `get_index_stats_hook` | Supply statistics for a column or index instead of the catalog's | Planned — [#274](https://github.com/villagesql/villagesql-server/issues/274) |
| `get_attavgwidth_hook`                            | Supply an average column width for cost estimation               | Planned — [#274](https://github.com/villagesql/villagesql-server/issues/274) |

### Executor

| PostgreSQL hook           | What it does                                                            | VillageSQL                                                                   |
| ------------------------- | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `ExecutorStart_hook`      | Run before a query starts executing                                     | Planned — [#702](https://github.com/villagesql/villagesql-server/issues/702) |
| `ExecutorRun_hook`        | Wrap row production, for masking, transformation, or per-row accounting | Planned — [#289](https://github.com/villagesql/villagesql-server/issues/289) |
| `ExecutorFinish_hook`     | Run after the last row, before teardown                                 | Planned — [#287](https://github.com/villagesql/villagesql-server/issues/287) |
| `ExecutorEnd_hook`        | Observe a finished statement and its execution statistics               | **Available** — `vsql::preview::statement_event`, post-execute phase         |
| `ExecutorCheckPerms_hook` | Approve or reject the table and column permissions a statement needs    | Planned — [#314](https://github.com/villagesql/villagesql-server/issues/314) |

PostgreSQL extensions that need per-operator detail get it by wrapping
`ExecutorRun_hook` at the node level. In VEF that is separate work, tracked in
[#340](https://github.com/villagesql/villagesql-server/issues/340).

### EXPLAIN

| PostgreSQL hook                 | What it does                                   | VillageSQL                                                                   |
| ------------------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------- |
| `ExplainOneQuery_hook`          | Replace or extend how a statement is explained | Planned — [#317](https://github.com/villagesql/villagesql-server/issues/317) |
| `explain_per_plan_hook`         | Add extension output once per explained plan   | Planned — [#317](https://github.com/villagesql/villagesql-server/issues/317) |
| `explain_per_node_hook`         | Add extension output for each plan node        | Planned — [#317](https://github.com/villagesql/villagesql-server/issues/317) |
| `explain_get_index_name_hook`   | Override the index name shown in output        | Planned — [#317](https://github.com/villagesql/villagesql-server/issues/317) |
| `explain_validate_options_hook` | Accept extension-defined `EXPLAIN` options     | Planned — [#317](https://github.com/villagesql/villagesql-server/issues/317) |

### Authentication and security

| PostgreSQL hook                                                               | What it does                                              | VillageSQL                                                                   |
| ----------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `ClientAuthentication_hook`                                                   | Take part in authentication, and observe its outcome      | **Partial** — see below                                                      |
| `check_password_hook`                                                         | Enforce a password policy when a password is set          | Planned — [#456](https://github.com/villagesql/villagesql-server/issues/456) |
| `ldap_password_hook`                                                          | Replace the LDAP bind used by the `ldap` auth method      | **Available** — implement the method itself with `vsql::preview::auth`       |
| `openssl_tls_init_hook`                                                       | Adjust the server's TLS context at startup                | Planned — [#458](https://github.com/villagesql/villagesql-server/issues/458) |
| `row_security_policy_hook_permissive`, `row_security_policy_hook_restrictive` | Add row filter predicates to a query based on the session | Planned — [#315](https://github.com/villagesql/villagesql-server/issues/315) |

PostgreSQL extensions use `ClientAuthentication_hook` for two different jobs,
and VEF covers one of them. An extension can implement an authentication method
of its own through the `vsql::preview::auth` capability, which is what
`vsql-oauth2` is built on. It cannot yet observe the result of authentication it
did not handle, which is how PostgreSQL's `auth_delay` and failed-login trackers
work. That part is
[#464](https://github.com/villagesql/villagesql-server/issues/464).

PostgreSQL maps external identities to database accounts through
`pg_ident.conf` rather than a hook. The VEF equivalent is
[#640](https://github.com/villagesql/villagesql-server/issues/640).

### Logging

| PostgreSQL hook | What it does                                                        | VillageSQL                                                                   |
| --------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `emit_log_hook` | See each log message before it is written, and filter or reroute it | Planned — [#316](https://github.com/villagesql/villagesql-server/issues/316) |

### Startup and shared memory

| PostgreSQL hook      | What it does                                 | VillageSQL                                                                   |
| -------------------- | -------------------------------------------- | ---------------------------------------------------------------------------- |
| `shmem_request_hook` | Request shared memory during startup         | Planned — [#282](https://github.com/villagesql/villagesql-server/issues/282) |
| `shmem_startup_hook` | Initialize that shared memory once it exists | Planned — [#282](https://github.com/villagesql/villagesql-server/issues/282) |

### Function manager

| PostgreSQL hook                | What it does                                                    | VillageSQL                                                                   |
| ------------------------------ | --------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `fmgr_hook`, `needs_fmgr_hook` | Run code around every function call, for auditing or sandboxing | Planned — [#287](https://github.com/villagesql/villagesql-server/issues/287) |

## Tell us what you need

We prioritize this work based on what extension authors ask for. If something
above is blocking an extension you want to build, add a 👍 to its issue and
describe your use case in a comment.
