Symptom: After replacing a .veb file and reinstalling, the extension still
runs old code.Cause: VillageSQL expands .veb files into _expanded/ on first load. If you
copy a new .veb without first running UNINSTALL EXTENSION, the server continues
using the previously-expanded .so that is already loaded in memory.Solution: Always follow the full UNINSTALL → replace → INSTALL cycle:
UNINSTALL EXTENSION my_extension;
Then replace the .veb file in veb_dir and reinstall:
INSTALL EXTENSION my_extension;
If the extension still shows old behavior, clear the expansion cache before reinstalling:
Error:Cannot uninstall extension: types in useSolution:
-- Attempt uninstall; the error identifies blocking columns by nameUNINSTALL EXTENSION my_extension;-- If blocked: ERROR HY000: Cannot drop extension `my_extension` as 1 column(s) depend on it,-- e.g. mydb.mytable.my_column has type MYTYPE-- Drop or alter the identified column(s), then retryDROP TABLE mydb.mytable;-- ORALTER TABLE mydb.mytable DROP COLUMN my_column;UNINSTALL EXTENSION my_extension;
Error:Failed to load VEF extension 'extension_name' with log message Extension name mismatchCause: The extension name in manifest.json doesn’t match the VEB filename.Debug steps:
Check VEB filename matches manifest:
# VEB filename: my_extension.veb# manifest.json should have:{ "name": "my_extension", # Must match VEB filename (without .veb) ...}
Verify manifest.json name field:
# Extract and check manifest from VEBtar -xOf /path/to/veb_dir/my_extension.veb manifest.json | grep name
Error:Cannot compare types X and Y in =Cause: Both sides of the comparison are custom types but from different types or extensions.
-- Example: comparing COMPLEX with UUID in a WHERE clauseSELECT * FROM t WHERE complex_col = uuid_col;-- ERROR: Cannot compare types vsql_complex.COMPLEX and vsql_uuid.UUID in =
Solution: Ensure both sides of a comparison use the same custom type. If you need to compare across types, convert one side explicitly using the appropriate type conversion function.Error:Unable to implicitly cast a non-custom type during compare with a custom type in =Cause: One side of the comparison is a custom type column and the other is a value (literal or column) that cannot be automatically converted to that type.
-- Example: comparing a custom type with an integer literalSELECT * FROM t WHERE complex_col = 42;-- ERROR: Unable to implicitly cast a non-custom type during compare...
Solution: String literals are automatically cast to the custom type using the type’s encode function. For other types (integers, floats), use an explicit conversion function:
-- Use a string literal instead (auto-cast works)SELECT * FROM t WHERE complex_col = '(1.0,2.0)';-- Or use the type's from_string method explicitlySELECT * FROM t WHERE complex_col = COMPLEX::from_string('(1.0,2.0)');
-- Find all columns using custom extension typesSELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPEFROM INFORMATION_SCHEMA.COLUMNSWHERE DATA_TYPE LIKE '%.%'ORDER BY DATA_TYPE, TABLE_SCHEMA, TABLE_NAME;
Data Safety: If tables use custom types from the extension, you must drop or alter those tables before uninstalling. Back up your data first.
Example:
-- Find columns using vsql_complex types before updatingSELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPEFROM INFORMATION_SCHEMA.COLUMNSWHERE DATA_TYPE LIKE 'vsql_complex.%';-- If columns exist, back up data and drop/alter them first-- Then proceed with updateUNINSTALL EXTENSION vsql_complex;-- (replace .veb file)INSTALL EXTENSION vsql_complex;
VillageSQL expands .veb files to _expanded/{name}/{sha256}/. Old versions accumulate over time.
# List expansion directoriesls -la /path/to/veb_dir/_expanded/# Compare with installed extensionsmysql -u root -p -e "SELECT EXTENSION_NAME FROM INFORMATION_SCHEMA.EXTENSIONS;"# Find the actual SHA256 directory name for a specific extensionls /path/to/veb_dir/_expanded/my_extension/# Remove the unused SHA256 directory using the name shown aboverm -rf /path/to/veb_dir/_expanded/my_extension/<sha256-from-ls>/
Server restart automatically cleans up orphaned expansion directories.
Custom types require ROW format binlog. STATEMENT and MIXED modes are not
supported for tables with custom type columns. INSERT, UPDATE, DELETE, and
ALTER TABLE operations on custom type columns all replicate correctly in ROW
format.INSTALL EXTENSION is not replicated — each server manages its own extensions.
Install the extension on every replica before replication starts, using the same
version as the source. The server enforces exact version matching; a version
mismatch stops replication.If a replica encounters a custom type it doesn’t recognize, replication stops at
the DDL statement — on CREATE TABLE or ALTER TABLE, before any dependent DML
is applied. Install the correct extension version, then resume:
mysqldump preserves fully qualified custom type names in the output. Logical
restores work as long as the extension is installed on the target server before
importing the dump.
Behavior with the Clone plugin, XtraBackup, and InnoDB Cluster / Group
Replication is not yet tested. Test your restore path before relying on it
in production.
When running VillageSQL in Docker, mount a local directory as veb_dir so you can add .veb files from the host without rebuilding the container.Docker Compose example: