Skip to main content
The vsql_complex extension is VillageSQL’s reference implementation for custom types using the C++ SDK—demonstrating production-ready extension patterns. Source: villagesql/examples/vsql-complex/ in VillageSQL repository

What vsql_complex Provides

COMPLEX type for complex numbers (a + bi) with arithmetic, utilities, and aggregation. Usage Example:

Directory Structure


VEF Registration Pattern

File: src/complex.cc vsql_complex uses the C++ SDK with VEF_GENERATE_ENTRY_POINTS():
Key patterns:
  • Single macro call registers everything — no manual SQL needed
  • Type objects are constexpr variables built with vsql::make_type<kName>(), where kName is a static constexpr const char[] used as a non-type template parameter
  • Type operations (.from_string<>(), .to_string<>(), .compare<>(), .hash<>()) are embedded in the type object — no separate .func() calls needed for them
  • .compare() enables ORDER BY and indexing; .hash() is optional
  • .intrinsic_default_str("(0,0)") sets the default value written when INSERT IGNORE or UPDATE IGNORE assigns NULL to a NOT NULL column of this type
  • Function registration uses make_func<&impl>("name") with .build()
  • Aggregate registration uses make_aggregate_func<State, &result_fn>("name") with .clear<&fn>() and .accumulate<&fn>(); the result function has signature void(const State&, ResultType)

Binary Storage Format

COMPLEX stores 16 bytes (little-endian):
  • Bytes 0-7: Real part (double)
  • Bytes 8-15: Imaginary part (double)
Encode/Decode (complex.cc):
Uses platform-independent byte-order functions for cross-platform compatibility.

Argument and Result Types

Implementations work with typed argument and result types rather than raw protocol structs: Arithmetic Example (from complex.cc):
Utility functions (from complex.cc):

Testing Strategy

Test File (test/t/complex_create.test):
Generate Results:
Run Tests:

Key Implementation Patterns


Manifest

File: manifest.json

Exporting and Importing Data with Custom Types

VillageSQL supports SELECT INTO OUTFILE and LOAD DATA INFILE for custom types, allowing you to export and import data while preserving custom type values.

SELECT INTO OUTFILE

Custom types serialize to their string representation when exported:
File contents (/tmp/signals_export.txt):

LOAD DATA INFILE

Load the exported data back into a table:

Export with Custom Delimiters

You can use custom field and line terminators:
Output:

Export with VDF Functions

Export computed values using extension functions:
Custom types are exported in their string representation format. Binary export with SELECT INTO DUMPFILE is not currently supported for custom types.

Next Steps

Create Extension

Build your own extension

Extension Architecture

Understand the internals

vsql_complex Source

View complete source code

Available Extensions

Browse extension catalog