VillageSQL Extension Template

August 14, 2026 · View on GitHub

A minimal template project for creating VillageSQL extensions. This template provides the essential structure and files needed to develop, build, and test custom VillageSQL extensions.

What This Is

This template demonstrates how to create a VillageSQL extension by implementing a simple "Hello, World!" function. It includes all the minimum required files and follows the VillageSQL extension framework (VEF) structure.

Project Structure

vsql_extension_template/
├── manifest.json           # Extension metadata (name, version, description, etc.)
├── CMakeLists.txt         # CMake build configuration
├── cmake/
│   └── FindVillageSQL.cmake  # CMake module for finding VillageSQL
├── src/
│   └── hello.cc           # C++ implementation using VEF API
└── mysql-test/
    ├── t/                 # Test files (.test)
    │   └── hello_basic.test
    └── r/                 # Expected results (.result)
        └── hello_basic.result

Prerequisites

  • CMake 3.18 or higher

  • C++ compiler with C++17 support

  • VillageSQL. You do not need to build the server from source. The install script sets up a server and the extension SDK under ~/.villagesql:

    curl -fsSL https://install.villagesql.com | INSTALL_METHOD=prebuilt bash
    

    (INSTALL_METHOD=prebuilt picks the path that installs the SDK locally; the Docker option keeps it inside the image.) A VillageSQL build directory works too, if you already have one.

📚 Full Documentation: Visit villagesql.com/docs for comprehensive guides on building extensions, architecture details, and more.

Building the Extension

  1. Create a build directory and configure:

    Linux:

    mkdir build
    cd build
    cmake .. -DVillageSQL_BUILD_DIR=$HOME/build/villagesql
    

    macOS:

    mkdir build
    cd build
    cmake .. -DVillageSQL_BUILD_DIR="$HOME/build/villagesql"
    

    If you used the install script, point at what it laid down:

    cmake -S . -B build -DVillageSQL_BUILD_DIR="$HOME/.villagesql/prebuilt"
    

    Note: VillageSQL_BUILD_DIR should point to your VillageSQL build directory. The VEB install directory is automatically set to ${VillageSQL_BUILD_DIR}/veb_output_directory. To build against an unpacked SDK on its own, use -DVillageSQL_SDK_DIR=/path/to/villagesql-extension-sdk-<version> — that sets no install directory, so copy the VEB to wherever the server reads them (SHOW VARIABLES LIKE 'veb_dir').

  2. Build the extension:

    make -j $(getconf _NPROCESSORS_ONLN)
    

    This creates the vsql_extension_template.veb package in the build directory.

  3. Install the VEB (optional):

make install

This copies the VEB to the directory specified by VillageSQL_VEB_INSTALL_DIR. If not using make install, you can manually copy the VEB file to your desired location.

Using the Extension

After building the VEB file, load the extension in VillageSQL:

INSTALL EXTENSION vsql_extension_template;

Then test the function:

SELECT hello_world();
-- Returns: Hello, World!

Note: Extension names use underscores, not hyphens (e.g., vsql_extension_template).

Testing

The extension includes test files using the MySQL Test Runner (MTR) framework.

Running Tests

Option 1 (Default): Using the installed VEB

This method assumes you have successfully run make install to install the VEB to your veb_dir.

Linux:

cd $HOME/build/villagesql/mysql-test
perl mysql-test-run.pl --suite=/path/to/vsql-extension-template/mysql-test

# Run with specific options
perl mysql-test-run.pl --suite=/path/to/vsql-extension-template/mysql-test --parallel=auto

macOS:

cd ~/build/villagesql/mysql-test
perl mysql-test-run.pl --suite=/path/to/vsql-extension-template/mysql-test

# Run with specific options
perl mysql-test-run.pl --suite=/path/to/vsql-extension-template/mysql-test --parallel=auto

Option 2: Testing a VEB you have not installed

Point MTR at any directory holding the .veb with --veb-source-dir. It copies from there in addition to the usual locations, so you can test a fresh build without make install:

cd $HOME/build/villagesql/mysql-test
perl mysql-test-run.pl \
  --veb-source-dir=/path/to/vsql-extension-template/build \
  --suite=/path/to/vsql-extension-template/mysql-test

Creating/Updating Test Results

To create or update expected test results:

Linux:

cd $HOME/build/villagesql/mysql-test
perl mysql-test-run.pl --suite=/path/to/test --record

macOS:

cd ~/build/villagesql/mysql-test
perl mysql-test-run.pl --suite=/path/to/test --record

Customizing This Template

To create your own extension:

  1. Update manifest.json:

    • Change name to your extension name (use underscores, e.g., my_extension_name)
    • Update description, author, and other metadata
  2. Update CMakeLists.txt:

    • Change EXTENSION_NAME to match your extension (use underscores)
    • Update the library name and source files in add_library()
    • Add dependencies if needed (e.g., find_package(), target_link_libraries())
  3. Implement Your Functions:

    • Modify src/hello.cc or create new source files
    • Include <villagesql/vsql.h> and using namespace vsql;
    • Use typed wrapper parameters: IntArg, RealArg, StringArg, StringResult, etc.
    • Register functions using VEF_GENERATE_ENTRY_POINTS() macro
  4. Create Tests:

    • Add .test files in the mysql-test/t/ directory
    • Generate expected results with --record flag
    • Verify your functions work correctly

Extension Development Tips

  • Extension Naming: Use underscores in extension names. A hyphenated name is a syntax error in INSTALL EXTENSION unless backtick-quoted, so underscores keep the statement quoting-free
  • Return Types: Common types are STRING, INT, REAL, or custom types
  • String Results: Write into out.buffer(), then call out.set_length(n)
  • NULL Handling: Call arg.is_null() on input args; call out.set_null() to return NULL
  • Error Handling: Call out.error(msg) to abort with an error; out.warning(msg) for a warning
  • Testing: Always test with various inputs including edge cases and NULL values

Example: Adding a New Function

  1. Add implementation to src/hello.cc:
void greet_impl(StringArg name, StringResult out) {
    if (name.is_null()) { out.set_null(); return; }
    auto val = name.value();
    auto buf = out.buffer();
    auto len = snprintf(buf.data(), buf.size(), "Hello, %.*s!",
                        (int)val.size(), val.data());
    out.set_length(len);
}
  1. Register in VEF_GENERATE_ENTRY_POINTS():
VEF_GENERATE_ENTRY_POINTS(
  make_extension()
    .func(make_func<&hello_world_impl>("hello_world")
      .returns(STRING)
      .no_params()
      .buffer_size(14)
      .build())
    .func(make_func<&greet_impl>("greet")
      .returns(STRING)
      .param(STRING)
      .buffer_size(256)
      .build())
)
  1. Rebuild and test:

    cd build
    make -j $(getconf _NPROCESSORS_ONLN)
    make install  # If VillageSQL_VEB_INSTALL_DIR is configured
    

    Then in VillageSQL:

    INSTALL EXTENSION vsql_extension_template;
    
    -- Call without prefix
    SELECT greet('VillageSQL');
    
    -- Or with explicit namespace
    SELECT vsql_extension_template.greet('VillageSQL');
    

Troubleshooting

Build Failures

VillageSQL SDK not found:

# Make sure VillageSQL_BUILD_DIR points to your build directory
# Linux:
cmake .. -DVillageSQL_BUILD_DIR=$HOME/build/villagesql

# macOS:
cmake .. -DVillageSQL_BUILD_DIR="$HOME/build/villagesql"

Extension Loading Issues

Extension not found after installation:

  • Verify the VEB file was copied to the correct directory
  • Check that INSTALL EXTENSION extension_name uses the correct name (underscores, not hyphens)
  • Restart the VillageSQL server if needed

Function not found:

  • Ensure the extension is installed: SELECT * FROM INFORMATION_SCHEMA.EXTENSIONS;
  • Try using explicit namespace: extension_name.function_name()
  • Check the server's VEF protocol support level to confirm compatibility with your extension: SELECT @@villagesql_vef_server_protocol;

Resources

License

This template is released under the GPL-2.0 license. See the license header in source files for details.

Contributing

When creating extensions based on this template, ensure your code follows the same license and includes appropriate copyright notices.