Skip to main content
Understanding VillageSQL’s extension architecture helps debug issues and optimize performance when building extensions.

Terminology

  • VEB (VillageSQL Extension Bundle) - The .veb file format, a tar archive containing manifest, library, and metadata
  • VEF (VillageSQL Extension Framework) - The SDK and C++ API for authoring extensions
  • VDF (VillageSQL Defined Function) - Functions registered through the VEF SDK using VEF_GENERATE_ENTRY_POINTS()
  • UDF (User-Defined Function) - Traditional MySQL functions registered via CREATE FUNCTION ... SONAME (legacy approach, still supported)

VDF Function Lookup

VDFs support both qualified and unqualified function calls:
Resolution order for unqualified function calls:
  1. System functions (built-in MySQL)
  2. UDFs (traditional user-defined functions)
  3. VDFs (extension functions) - only if exactly one function with that name exists
  4. Stored functions (created with CREATE FUNCTION)
Performance: For hot code paths, use qualified calls (extension_name.function_name()) to skip the resolution chain and directly invoke the extension function.

VEB File Format

VillageSQL extensions are distributed as .veb (VillageSQL Extension Bundle) files - tar archives containing:

manifest.json Schema

  • name: Must match extension name used in SQL (lowercase_with_underscores)
  • version: Semantic version (MAJOR.MINOR.PATCH)
  • description, author, license: Optional metadata

Extension Lifecycle

Installation Flow

Rollback: If any step fails, all changes are undone and the .so is unloaded. Symbol Isolation: Extensions are loaded with RTLD_LOCAL flag, ensuring symbols from one extension don’t conflict with symbols from other extensions. This prevents naming collisions when multiple extensions use common library names or function names.
The veb_dir system variable points to the directory where .veb extension files are stored.

Uninstallation Flow

Dependency prevention: Cannot uninstall if table columns use the extension’s custom types.

Expansion Directory Structure

VillageSQL expands .veb files to support multiple versions:
Why SHA256 directories?
  • Test new versions without overwriting
  • Enable rollback
  • Prevent “same version, different code”
Cleanup: Orphaned SHA256 directories are removed on server restart.

Victionary Caching Layer

VictionaryClient maintains in-memory caches of system metadata for O(log n) lookups.

Cached Tables

Cache Operations

Cache invalidation: Automatic during DDL operations (INSTALL/UNINSTALL EXTENSION). Memory overhead: ~100 bytes per entry.

Custom Type System

Type Resolution

Implementation Types

Custom types map to MySQL storage types:

Concurrency & Transaction Behavior

Thread Safety Model

Extension functions are called in a per-row execution model:
  • Isolated per-row execution: Each function call gets its own result buffer (thread-safe by design)
  • Prerun/Postrun hooks: Per-statement setup/cleanup, called once per SQL statement
  • No guaranteed isolation: Multiple connections may call your functions concurrently
  • Best practice: Avoid global state; use function parameters and return values
VillageSQL does not guarantee thread isolation for extension functions. If you use global variables or shared state, protect them with mutexes or locks.

Transaction Behavior

Extension functions should follow these best practices:
  • Design functions to be stateless when possible
  • Avoid persistent side effects (file writes, external API calls) in functions
  • If using prerun/postrun state, handle cleanup appropriately

Performance Considerations

Optimization: Use prerun hooks to cache expensive per-statement setup instead of repeating work per-row.

Custom Type Performance


Security & Debugging

Security Model

Trust model: Extensions run with full server privileges.
  • No sandboxing or permission system
  • Extensions can read any file, access network, execute code
  • Trust implications: Only install extensions from trusted sources
Installation security: Runs as villagesql_extension_installer user (context switch).
Enable verbose logging:
GDB debugging:
Check dependencies:
Common errors:
  • Undefined symbol: Check extern "C" linkage
  • Cannot open shared object: Check library dependencies
  • Crash on UDF call: Check NULL pointer handling

Schema Validation

On server startup, SchemaManager validates system table schemas:
Failure scenarios:
  • Missing table → Create from villagesql_schema.sql
  • Wrong schema → Error and refuse to start
  • Version mismatch → Run upgrade scripts
Server version:
Source builds include the git commit hash:

Next Steps

Create Extension

Build your first extension

System Reference

System tables and views

Examples

Study vsql_complex implementation

Managing Extensions

Monitor and troubleshoot