This file provides guidance to AI coding assistants when working with code in this repository.
Note: Also check AGENTS.local.md for additional local development instructions when present.
This is a VillageSQL extension that provides cryptographic functions for hashing, encryption, and random data generation. The extension uses OpenSSL and implements functionality similar to PostgreSQL's pgcrypto module, complementing MySQL's built-in cryptographic functions.
IMPORTANT: Always build in the build/ directory, never in the source root. Building in the source root creates files that should not be checked into git.
-
Configure CMake with required paths:
mkdir build cd build cmake .. -DVillageSQL_BUILD_DIR=/path/to/villagesql/buildNote:
VillageSQL_BUILD_DIR: Path to VillageSQL build directory (contains the staged SDK andveb_output_directory)
-
Build the extension:
make
-
Install the VEB (optional):
make install
The build process:
- Uses CMake with the VillageSQL Extension Framework SDK
- Compiles C++ source files into shared library
vsql_crypto.so - Packages library with
manifest.jsonintovsql_crypto.vebpackage usingVEF_CREATE_VEB()macro - VEB can be installed to VillageSQL for use
- OpenSSL libraries are linked during build
See AGENTS.local.md for machine-specific build paths and configurations.
Core Components:
src/crypto.cc- VEF implementations for cryptographic functionsmanifest.json- Extension metadata (name, version, description, author, license)CMakeLists.txt- CMake build configurationcmake/FindVillageSQL.cmake- CMake module to locate VillageSQL SDKmysql-test/t/- Test files directory (.testfiles using MTR framework)mysql-test/r/- Expected test results directory (.resultfiles)
Available Functions:
crypto_version()- Return OpenSSL version informationdigest(data, type)- Compute cryptographic hash (MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512)hmac(data, key, type)- Compute HMAC (Hash-based Message Authentication Code)encrypt(data, key, type)- Encrypt data with AES (128/192/256-bit)decrypt(data, key, type)- Decrypt encrypted datagen_salt(type, iter_count)- Generate salt for password hashing using PBKDF2 (SHA-256/SHA-512)crypt(password, salt)- Hash password using PBKDF2 with configurable iterationsgen_random_bytes(count)- Generate cryptographically secure random bytesgen_random_uuid()- Generate random UUID v4
Error Handling:
- Functions return NULL for invalid inputs (unsupported algorithms, NULL arguments, corrupted data)
- Functions set result->type to IS_NULL for errors
- This behavior is validated in the
crypto_errors.testtest suite
Dependencies:
- VillageSQL Extension Framework SDK
- C++ compiler with C++17 support
- OpenSSL (linked during build)
Code Organization:
- File naming: lowercase with underscores (e.g.,
crypto.cc) - Function naming: lowercase with underscores (e.g.,
gen_random_uuid) - Variable naming: lowercase with underscores (e.g.,
digest_len) - All cryptographic operations use OpenSSL APIs (EVP, HMAC, RAND)
This extension uses the Protocol V3 stable SDK (<villagesql/vsql.h>).
#include <villagesql/vsql.h>
using namespace vsql;
void my_function_impl(StringArg arg1, StringArg arg2, StringResult result) {
if (arg1.is_null() || arg2.is_null()) { result.set_null(); return; }
std::string_view s = arg1.value();
// write to result.buffer(), then call result.set_length(n)
}Typed argument wrappers: StringArg, IntArg, RealArg. Result wrappers: StringResult, IntResult, RealResult. Use result.set_null() for NULL, result.warning("msg") for soft errors (Warning 3200 + NULL return), result.error("msg") for hard errors (ERROR 3200).
VEF_GENERATE_ENTRY_POINTS(
make_extension()
.func(make_func<&my_function_impl>("my_function")
.returns(STRING).param(STRING).param(INT).buffer_size(1024).build())
)Extension name and version come from manifest.json; make_extension() takes no arguments in V3.
The extension includes comprehensive test files using the MySQL Test Runner (MTR) framework:
- Test Location:
mysql-test/t/directory contains.testfiles with SQL test commandsmysql-test/r/directory contains.resultfiles with expected output
- Test Files:
crypto_basic.test- Tests all functions with valid inputs (happy path)crypto_errors.test- Tests error handling for invalid inputs, NULL values, and edge cases
Option 1 (Default): Using installed VEB
This method assumes the VEB is already installed to your VillageSQL veb_dir:
cd /path/to/mysql-test
perl mysql-test-run.pl --suite=/path/to/vsql-crypto/mysql-test
# Run individual test
perl mysql-test-run.pl --suite=/path/to/vsql-crypto/mysql-test crypto_basicOption 2: Using a specific VEB file
Use this to test a specific VEB build without installing it first:
cd /path/to/mysql-test
VSQL_CRYPTO_VEB=/path/to/vsql-crypto/build/vsql_crypto.veb \
perl mysql-test-run.pl --suite=/path/to/vsql-crypto/mysql-testUse --record flag to generate or update expected .result files:
cd /path/to/mysql-test
VSQL_CRYPTO_VEB=/path/to/vsql-crypto/build/vsql_crypto.veb \
perl mysql-test-run.pl --suite=/path/to/vsql-crypto/mysql-test --record- Tests should validate function output and behavior
- Each test should install the extension, run tests, and clean up (uninstall extension)
- Error Handling: Functions return NULL for errors (result->type = IS_NULL)
After building the extension, install it in VillageSQL:
INSTALL EXTENSION vsql_crypto;Then test the functions:
SELECT HEX(digest('test', 'sha256'));
SELECT gen_random_uuid();
SELECT HEX(hmac('data', 'key', 'sha256'));To add new cryptographic functions to this extension:
-
Implement the VDF in
src/crypto.cc:- Add the implementation function with signature:
void func_impl(vef_context_t*, vef_invalue_t*..., vef_vdf_result_t*) - Use OpenSSL APIs for cryptographic operations
- Check for NULL arguments and set
result->type = IS_NULLon error - Set
result->type = IS_VALUEand populateresult->str_buforresult->bin_bufon success - Include copyright header if creating new files
- Add the implementation function with signature:
-
Register the function in the extension:
- Add function registration in
VEF_GENERATE_ENTRY_POINTSblock - Use
make_func<&func_impl>("function_name")with appropriate.returns(),.param(), and.buffer_size()settings
- Add function registration in
-
Create tests:
- Add happy path tests to
mysql-test/t/crypto_basic.testor create new test files - Add error handling tests to
mysql-test/t/crypto_errors.test - Generate expected results using
--recordflag - Test various inputs including edge cases, NULL values, and invalid parameters
- Add happy path tests to
-
Update documentation:
- Add function descriptions to README.md
- Update AGENTS.md with new function signatures
All source code files (.cc, .h, .cpp, .hpp) and CMake files (CMakeLists.txt) must include the following copyright header at the top of the file:
/* Copyright (c) 2025 VillageSQL Contributors
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
When creating new source files, always include this copyright block before any code or includes.
When asked to add functionality to this extension:
- Adding a new function: Create the VDF implementation in src/crypto.cc, register it in VEF_GENERATE_ENTRY_POINTS, create both happy path and error handling tests
- Modifying build: Edit CMakeLists.txt, ensure proper library linking
- Adding dependencies: Update CMakeLists.txt with find_package() or target_link_libraries()
- Testing:
- Create or update
.testfiles inmysql-test/t/directory - Add both valid input tests (crypto_basic.test) and error handling tests (crypto_errors.test)
- Generate expected results with
--recordflag - Verify all tests pass with
perl mysql-test-run.pl --suite=<path>
- Create or update
- Documentation: Update README.md and AGENTS.md to reflect new functionality
Always maintain consistency with existing code style and include proper copyright headers.