ducktinycc
DuckDB-C-Erweiterung für im Prozess JIT-kompilierte C-UDFs über TinyCC — eigenständig, keine externe Laufzeitumgebung erforderlich
Maintainer: sounkou-bioinfo
Installation und Laden
INSTALL ducktinycc FROM community;LOAD ducktinycc;Beispiel
-- Load the extensionLOAD ducktinycc;
-- Compile and register a simple C function as a SQL UDFSELECT ok, mode, codeFROM 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 UDFSELECT hello_from_c() AS msg;Über ducktinycc
DuckTinyCC kompiliert und registriert C-Skalar-UDFs aus SQL mit TinyCC (libtcc), im Prozess.
Wichtige SQL-Einstiegspunkte:
| Function | Purpose |
|---|---|
| tcc_module(…) | Sitzungskonfiguration, Build-Staging, Codegenerierung, Kompilierung, Registrierung |
| tcc_system_paths(…) | Effektive TinyCC-Include-/Bibliothekssuchpfade anzeigen |
| tcc_library_probe(…) | Kandidatenbibliotheksdateien und normalisierte Linknamen prüfen |
Compile-/Codegen- und C-Typ-Hilfsmodi (über tcc_module):
| Mode | Purpose |
|---|---|
| quick_compile | Einmalig Quelle + Codegenerierung + Kompilierung + Registrierung |
| compile | Kompilieren/Registrieren aus vorgestagten Sitzungsquellen/-bindungen |
| codegen_preview | Generierten Wrapper-C-Quelltext ohne Kompilierung/Laden ausgeben |
| c_struct | Struct-Hilfs-UDFs aus Feldspezifikationen erzeugen und registrieren |
| c_union | Union-Hilfs-UDFs aus Feldspezifikationen erzeugen und registrieren |
| c_bitfield | Bitfield-Struct-Hilfs-UDFs erzeugen und registrieren |
| c_enum | Enum-Konstanten-Hilfs-UDFs erzeugen und registrieren |
Namensschema der generierten Hilfsfunktionen:
| Helper mode | Generated SQL function pattern |
|---|---|
| c_struct | struct_ |
| c_union | union_ |
| c_bitfield | struct_ |
| c_enum | enum_ |
Unterstützung für Typsignaturen (return_type / arg_types):
| Token family | Examples |
|---|---|
| Scalars | void (nur Rückgabe), bool, i8/u8/i16/u16/i32/u32/i64/u64, f32/f64, ptr, varchar, blob, uuid, date, time, timestamp, interval, decimal |
| Composites (recursive) | list |
Entsprechungen der SQL-↔-C-Brücke:
| 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) bei der Registrierung) |
Ergebnisschemas der Funktionen:
| 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-/Laufzeitmodell:
- Wrapper werden aus return_type/arg_types erzeugt und über ducktinycc_register_signature(…) registriert
- wrapper_mode unterstützt zeilen- und batchweise Ausführungspfade
- Code wird im Speicher kompiliert + relokiert (kein separates Shared-Library-Artefakt)
- Die zweimalige Registrierung desselben sql_name in einer Sitzung liefert false/E_INIT_FAILED (plattformübergreifend konsistent); vor erneuter Registrierung mit tcc_new_state zurücksetzen
Stabilität von Skalar-UDFs:
- compile, quick_compile und codegen_preview akzeptieren stability := ‘consistent’ | ‘volatile’
- tinycc_bind kann die Stabilität für eine spätere Kompilierung vorbereiten; ein expliziter stability-Wert bei compile/quick_compile/codegen_preview überschreibt den vorgestagten Wert
- Verwenden Sie volatile für RNGs, Zähler, Uhren, Allokation, I/O, Callbacks oder Lesezugriffe auf veränderlichen externen Speicher, damit DuckDB die Funktion erneut ausführt und Seiteneffekte nicht constant-foldet
- Generierte Hilfsmodi setzen intern eine explizite Hilfsstabilität: reine Metadaten-/Enum-Helfer sind consistent, während Allokations-/Free-/Setter-/Getter-Helfer für veränderlichen Speicher volatile sind
Eingebettete Laufzeitumgebung (eigenständig):
- libtcc1.a und alle TinyCC-Include-Header (stdarg.h, stddef.h, tccdefs.h usw.) werden zur Build-Zeit in die Erweiterungsbinary eingebettet
- Beim ersten compile- oder quick_compile-Aufruf extrahiert tcc_ensure_embedded_runtime() sie in ein inhaltshash-adressiertes temporäres Verzeichnis (z. B. /tmp/ducktinycc_
/) - Folgeaufrufe im selben Prozess nutzen dieses Verzeichnis erneut, ohne erneut zu extrahieren
- Nach der Bereitstellung ist keine separate TinyCC-Installation oder Laufzeitpfadkonfiguration nötig
- tcc_system_paths() zeigt den aktiven Laufzeitpfad und, ob er aus der eingebetteten Extraktion aufgelöst wurde
Projektdetails und Beispiele: https://github.com/sounkou-bioinfo/DuckTinyCC
Community package excludes WASM targets.
Additional Notes: Generated and helper functions are SQL scalar UDFs; only tcc_module(…), tcc_system_paths(…), and tcc_library_probe(…) are table functions. For library linking, we can pass short names (m, z, c), explicit filenames (libfoo.so, foo.dll, .a, .lib), or path-like values. Because DuckTinyCC uses -nostdlib by default, use library := ‘c’ when generated code needs libc symbols that are not otherwise injected. Pointer helpers are low-level interop tools; for most workflows, handle-based access is safer than raw tcc_dataptr
Hinzugefügte Funktionen
| 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 |
Überladene Funktionen
Diese Erweiterung fügt keine Funktionsüberladungen hinzu.
Hinzugefügte Typen
Diese Erweiterung fügt keine Typen hinzu.
Hinzugefügte Einstellungen
Diese Erweiterung fügt keine Einstellungen hinzu.