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=prebuiltpicks 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
-
Create a build directory and configure:
Linux:
mkdir build cd build cmake .. -DVillageSQL_BUILD_DIR=$HOME/build/villagesqlmacOS:
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_DIRshould 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'). -
Build the extension:
make -j $(getconf _NPROCESSORS_ONLN)This creates the
vsql_extension_template.vebpackage in the build directory. -
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:
-
Update
manifest.json:- Change
nameto your extension name (use underscores, e.g.,my_extension_name) - Update
description,author, and other metadata
- Change
-
Update
CMakeLists.txt:- Change
EXTENSION_NAMEto 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())
- Change
-
Implement Your Functions:
- Modify
src/hello.ccor create new source files - Include
<villagesql/vsql.h>andusing namespace vsql; - Use typed wrapper parameters:
IntArg,RealArg,StringArg,StringResult, etc. - Register functions using
VEF_GENERATE_ENTRY_POINTS()macro
- Modify
-
Create Tests:
- Add
.testfiles in themysql-test/t/directory - Generate expected results with
--recordflag - Verify your functions work correctly
- Add
Extension Development Tips
- Extension Naming: Use underscores in extension names. A hyphenated name is a syntax error in
INSTALL EXTENSIONunless 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 callout.set_length(n) - NULL Handling: Call
arg.is_null()on input args; callout.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
- 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);
}
- 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())
)
-
Rebuild and test:
cd build make -j $(getconf _NPROCESSORS_ONLN) make install # If VillageSQL_VEB_INSTALL_DIR is configuredThen 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_nameuses 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.