Search Shortcut cmd + k | ctrl + k
ducktinycc

DuckDB C extension for in-process JIT compiled C UDFs via TinyCC — self-contained, no external runtime required

Maintainer(s): sounkou-bioinfo

Installing and Loading

INSTALL ducktinycc FROM community;
LOAD ducktinycc;

Example

-- Load the extension
LOAD ducktinycc;

-- Compile and register a simple C function as a SQL UDF
SELECT ok, mode, code
FROM tcc_module(
  mode := 'quick_compile',
  source := 'const char *hello_from_c(void){ return "hello from C"; }',
  symbol := 'hello_from_c',
  sql_name := 'hello_from_c',
  return_type := 'varchar',
  arg_types := []
);

-- Call the registered C UDF 
SELECT hello_from_c() AS msg;

About ducktinycc

DuckTinyCC compiles and registers C scalar UDFs from SQL using TinyCC (libtcc), in-process.

Main SQL entrypoints:

Function Purpose
tcc_module(…) Session config, build staging, codegen, compile, registration
tcc_system_paths(…) Show effective TinyCC include/library search paths
tcc_library_probe(…) Probe candidate library files and normalized link names

Compile/codegen and C-type helper modes (via tcc_module):

Mode Purpose
quick_compile One-shot source + codegen + compile + register
compile Compile/register from staged session sources/bindings
codegen_preview Emit generated wrapper C source without compile/load
c_struct Generate + register struct helper UDFs from field specs
c_union Generate + register union helper UDFs from field specs
c_bitfield Generate + register bitfield struct helper UDFs
c_enum Generate + register enum constant helper UDFs

Generated helper naming:

Helper mode Generated SQL function pattern
c_struct struct__new/free/get_*/set_*/off_*/addr/sizeof/alignof
c_union union__new/free/get_*/set_*/off_*/addr/sizeof/alignof
c_bitfield struct__get_*/set_*/sizeof/alignof
c_enum enum__, enum__sizeof

Type signature support (return_type / arg_types):

Token family Examples
Scalars void (return only), bool, i8/u8/i16/u16/i32/u32/i64/u64, f32/f64, ptr, varchar, blob, uuid, date, time, timestamp, interval, decimal
Composites (recursive) list, type[], type[N], struct<name:type;...>, map<key_type;value_type>, union<name:type;...>

SQL <-> C bridge correspondences:

SQL token family C bridge type
varchar const char *
blob ducktinycc_blob_t
list<…>, type[] ducktinycc_list_t
type[N] ducktinycc_array_t
struct<…> ducktinycc_struct_t
map<…> ducktinycc_map_t
union<…> ducktinycc_union_t
decimal ducktinycc_decimal_t (DuckDB DECIMAL(18,3) at registration)

Function result schemas:

Function Result columns
tcc_module(…) ok BOOLEAN, mode VARCHAR, phase VARCHAR, code VARCHAR, message VARCHAR, detail VARCHAR, sql_name VARCHAR, symbol VARCHAR, artifact_id VARCHAR, connection_scope VARCHAR
tcc_system_paths(…) kind VARCHAR, key VARCHAR, value VARCHAR, exists BOOLEAN, detail VARCHAR
tcc_library_probe(…) kind VARCHAR, key VARCHAR, value VARCHAR, exists BOOLEAN, detail VARCHAR

Codegen/runtime model:

  • wrappers are generated from return_type/arg_types and registered through ducktinycc_register_signature(…)
  • wrapper_mode supports row and batch execution paths
  • code is compiled + relocated in-memory (no separate shared-library artifact)
  • registering the same sql_name twice in a session returns false/E_INIT_FAILED (consistent across platforms); use tcc_new_state to reset before re-registering

Embedded runtime (self-contained):

  • libtcc1.a and all TinyCC include headers (stdarg.h, stddef.h, tccdefs.h, etc.) are baked into the extension binary at build time
  • on the first compile or quick_compile call, tcc_ensure_embedded_runtime() extracts them to a content-hash-keyed temp directory (e.g. /tmp/ducktinycc_/)
  • subsequent calls in the same process reuse that directory without re-extracting
  • no separate TinyCC installation or runtime path configuration is needed after deployment
  • tcc_system_paths() shows the active runtime path and whether it resolved from the embedded extraction

Project details and examples: https://github.com/sounkou-bioinfo/DuckTinyCC

Community package excludes WASM targets.

Added Functions

function_name function_type description comment examples
tcc_alloc scalar NULL NULL  
tcc_dataptr scalar NULL NULL  
tcc_free_ptr scalar NULL NULL  
tcc_library_probe table NULL NULL  
tcc_module table NULL NULL  
tcc_ptr_add scalar NULL NULL  
tcc_ptr_size scalar NULL NULL  
tcc_read_bytes scalar NULL NULL  
tcc_read_f32 scalar NULL NULL  
tcc_read_f64 scalar NULL NULL  
tcc_read_i16 scalar NULL NULL  
tcc_read_i32 scalar NULL NULL  
tcc_read_i64 scalar NULL NULL  
tcc_read_i8 scalar NULL NULL  
tcc_read_u16 scalar NULL NULL  
tcc_read_u32 scalar NULL NULL  
tcc_read_u64 scalar NULL NULL  
tcc_read_u8 scalar NULL NULL  
tcc_system_paths table NULL NULL  
tcc_write_bytes scalar NULL NULL  
tcc_write_f32 scalar NULL NULL  
tcc_write_f64 scalar NULL NULL  
tcc_write_i16 scalar NULL NULL  
tcc_write_i32 scalar NULL NULL  
tcc_write_i64 scalar NULL NULL  
tcc_write_i8 scalar NULL NULL  
tcc_write_u16 scalar NULL NULL  
tcc_write_u32 scalar NULL NULL  
tcc_write_u64 scalar NULL NULL  
tcc_write_u8 scalar NULL NULL  

Overloaded Functions

This extension does not add any function overloads.

Added Types

This extension does not add any types.

Added Settings

This extension does not add any settings.