The DuckDB C API supports a rich set of data types, from simple integers to complex nested structures.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/duckdb/duckdb/llms.txt
Use this file to discover all available pages before exploring further.
Type Enumeration
All DuckDB types are represented by theduckdb_type enum (from duckdb.h:61-141):
typedef enum DUCKDB_TYPE {
DUCKDB_TYPE_INVALID = 0,
// Numeric types
DUCKDB_TYPE_BOOLEAN = 1,
DUCKDB_TYPE_TINYINT = 2, // int8_t
DUCKDB_TYPE_SMALLINT = 3, // int16_t
DUCKDB_TYPE_INTEGER = 4, // int32_t
DUCKDB_TYPE_BIGINT = 5, // int64_t
DUCKDB_TYPE_UTINYINT = 6, // uint8_t
DUCKDB_TYPE_USMALLINT = 7, // uint16_t
DUCKDB_TYPE_UINTEGER = 8, // uint32_t
DUCKDB_TYPE_UBIGINT = 9, // uint64_t
DUCKDB_TYPE_FLOAT = 10, // float
DUCKDB_TYPE_DOUBLE = 11, // double
DUCKDB_TYPE_HUGEINT = 16, // 128-bit integer
DUCKDB_TYPE_UHUGEINT = 32, // 128-bit unsigned
DUCKDB_TYPE_DECIMAL = 19,
// Temporal types
DUCKDB_TYPE_DATE = 13,
DUCKDB_TYPE_TIME = 14,
DUCKDB_TYPE_TIMESTAMP = 12,
DUCKDB_TYPE_TIMESTAMP_S = 20,
DUCKDB_TYPE_TIMESTAMP_MS = 21,
DUCKDB_TYPE_TIMESTAMP_NS = 22,
DUCKDB_TYPE_TIMESTAMP_TZ = 31,
DUCKDB_TYPE_TIME_TZ = 30,
DUCKDB_TYPE_TIME_NS = 39,
DUCKDB_TYPE_INTERVAL = 15,
// String types
DUCKDB_TYPE_VARCHAR = 17,
DUCKDB_TYPE_BLOB = 18,
// Complex types
DUCKDB_TYPE_LIST = 24,
DUCKDB_TYPE_STRUCT = 25,
DUCKDB_TYPE_MAP = 26,
DUCKDB_TYPE_ARRAY = 33,
DUCKDB_TYPE_UNION = 28,
// Special types
DUCKDB_TYPE_UUID = 27,
DUCKDB_TYPE_ENUM = 23,
DUCKDB_TYPE_BIT = 29,
DUCKDB_TYPE_ANY = 34,
} duckdb_type;
Primitive Types
Boolean
// Create
bool value = true;
duckdb_append_bool(appender, value);
// Read
bool result = duckdb_value_boolean(&result, col, row);
Integer Types
- Signed
- Unsigned
// TINYINT (-128 to 127)
int8_t tiny = -100;
duckdb_append_int8(appender, tiny);
int8_t val = duckdb_value_int8(&result, col, row);
// SMALLINT (-32768 to 32767)
int16_t small = -30000;
duckdb_append_int16(appender, small);
// INTEGER (-2^31 to 2^31-1)
int32_t integer = 1000000;
duckdb_append_int32(appender, integer);
// BIGINT (-2^63 to 2^63-1)
int64_t big = 9223372036854775807LL;
duckdb_append_int64(appender, big);
// UTINYINT (0 to 255)
uint8_t utiny = 200;
duckdb_append_uint8(appender, utiny);
// USMALLINT (0 to 65535)
uint16_t usmall = 60000;
duckdb_append_uint16(appender, usmall);
// UINTEGER (0 to 2^32-1)
uint32_t uint = 4000000000U;
duckdb_append_uint32(appender, uint);
// UBIGINT (0 to 2^64-1)
uint64_t ubig = 18446744073709551615ULL;
duckdb_append_uint64(appender, ubig);
Floating Point
// FLOAT (32-bit)
float f = 3.14159f;
duckdb_append_float(appender, f);
float fval = duckdb_value_float(&result, col, row);
// DOUBLE (64-bit)
double d = 2.718281828459045;
duckdb_append_double(appender, d);
double dval = duckdb_value_double(&result, col, row);
HUGEINT (128-bit Integer)
typedef struct {
uint64_t lower;
int64_t upper;
} duckdb_hugeint;
// Create HUGEINT
duckdb_hugeint huge;
huge.lower = 1000000000ULL;
huge.upper = 5000LL;
duckdb_append_hugeint(appender, huge);
// Read HUGEINT
duckdb_hugeint val = duckdb_value_hugeint(&result, col, row);
// Convert to/from double
double d = duckdb_hugeint_to_double(huge);
duckdb_hugeint huge2 = duckdb_double_to_hugeint(d);
String Types
VARCHAR
// Append string
const char *str = "Hello, DuckDB!";
duckdb_append_varchar(appender, str);
// With explicit length
duckdb_append_varchar_length(appender, "test", 4);
// Read string (must free!)
char *result_str = duckdb_value_varchar(&result, col, row);
printf("%s\n", result_str);
duckdb_free(result_str);
BLOB (Binary Data)
// Create blob
const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
duckdb_append_blob(appender, data, sizeof(data));
// Read blob
duckdb_blob blob = duckdb_value_blob(&result, col, row);
printf("Blob size: %zu\n", blob.size);
// Process blob.data...
duckdb_free(blob.data);
Temporal Types
DATE
typedef struct {
int32_t days; // Days since 1970-01-01
} duckdb_date;
// Create date
duckdb_date date;
date.days = 18628; // 2021-01-01
duckdb_append_date(appender, date);
// Read date
duckdb_date result_date = duckdb_value_date(&result, col, row);
// Date conversion
duckdb_date_struct parts = duckdb_from_date(date);
printf("%d-%d-%d\n", parts.year, parts.month, parts.day);
duckdb_date reconstructed = duckdb_to_date(parts);
TIME
typedef struct {
int64_t micros; // Microseconds since 00:00:00
} duckdb_time;
// Create time
duckdb_time time;
time.micros = 43200000000LL; // 12:00:00 (noon)
duckdb_append_time(appender, time);
// Time conversion
duckdb_time_struct parts = duckdb_from_time(time);
printf("%02d:%02d:%02d.%06d\n", parts.hour, parts.min, parts.sec, parts.micros);
TIMESTAMP
typedef struct {
int64_t micros; // Microseconds since epoch
} duckdb_timestamp;
// Create timestamp
duckdb_timestamp ts;
ts.micros = 1609459200000000LL; // 2021-01-01 00:00:00 UTC
duckdb_append_timestamp(appender, ts);
// Timestamp conversion
duckdb_timestamp_struct parts = duckdb_from_timestamp(ts);
printf("%d-%02d-%02d %02d:%02d:%02d\n",
parts.date.year, parts.date.month, parts.date.day,
parts.time.hour, parts.time.min, parts.time.sec);
INTERVAL
typedef struct {
int32_t months;
int32_t days;
int64_t micros;
} duckdb_interval;
// Create interval: 1 year, 2 months, 3 days, 4 hours
duckdb_interval interval;
interval.months = 14; // 1 year + 2 months
interval.days = 3;
interval.micros = 4 * 3600 * 1000000LL; // 4 hours
duckdb_append_interval(appender, interval);
Complex Types
LIST
Lists are variable-length arrays of the same type:CREATE TABLE lists(id INTEGER, values INTEGER[]);
// Access list elements (simplified)
duckdb_result result;
duckdb_query(con, "SELECT [1, 2, 3, 4, 5]", &result);
// Use duckdb_list_vector_get_child() for detailed access
STRUCT
Structs are fixed-length collections of named fields:CREATE TABLE structs(id INTEGER, person STRUCT(name VARCHAR, age INTEGER));
// Query struct
duckdb_result result;
duckdb_query(con, "SELECT {'name': 'Alice', 'age': 30}", &result);
// Use duckdb_struct_vector_get_child() for field access
MAP
Maps are key-value pairs:CREATE TABLE maps(id INTEGER, properties MAP(VARCHAR, INTEGER));
Type Checking
// Get column type
duckdb_type type = duckdb_column_type(&result, col);
switch (type) {
case DUCKDB_TYPE_INTEGER:
int32_t ival = duckdb_value_int32(&result, col, row);
break;
case DUCKDB_TYPE_VARCHAR:
char *sval = duckdb_value_varchar(&result, col, row);
// Use sval...
duckdb_free(sval);
break;
case DUCKDB_TYPE_DOUBLE:
double dval = duckdb_value_double(&result, col, row);
break;
default:
// Handle other types
break;
}
NULL Handling
// Check for NULL
if (duckdb_value_is_null(&result, col, row)) {
printf("Value is NULL\n");
} else {
// Access value
int32_t val = duckdb_value_int32(&result, col, row);
}
// Append NULL
duckdb_append_null(appender);
Type Conversion
duckdb_value_varchar() can convert any type to string representation:// Convert any value to string
char *str = duckdb_value_varchar(&result, col, row);
printf("Value as string: %s\n", str);
duckdb_free(str);
Complete Example
#include "duckdb.h"
#include <stdio.h>
int main() {
duckdb_database db;
duckdb_connection con;
duckdb_open(NULL, &db);
duckdb_connect(db, &con);
// Create table with various types
duckdb_query(con,
"CREATE TABLE types_demo("
" id INTEGER, "
" name VARCHAR, "
" balance DOUBLE, "
" birth_date DATE, "
" is_active BOOLEAN, "
" data BLOB"
")", NULL);
// Insert using appender
duckdb_appender appender;
duckdb_appender_create(con, NULL, "types_demo", &appender);
// Row 1
duckdb_append_int32(appender, 1);
duckdb_append_varchar(appender, "Alice");
duckdb_append_double(appender, 1234.56);
duckdb_date date;
date.days = 18628;
duckdb_append_date(appender, date);
duckdb_append_bool(appender, true);
uint8_t blob_data[] = {0xDE, 0xAD, 0xBE, 0xEF};
duckdb_append_blob(appender, blob_data, sizeof(blob_data));
duckdb_appender_end_row(appender);
duckdb_appender_close(appender);
// Query and print
duckdb_result result;
if (duckdb_query(con, "SELECT * FROM types_demo", &result) == DuckDBSuccess) {
idx_t cols = duckdb_column_count(&result);
// Print column types
for (idx_t i = 0; i < cols; i++) {
printf("%s (%d)\t",
duckdb_column_name(&result, i),
duckdb_column_type(&result, i));
}
printf("\n");
duckdb_destroy_result(&result);
}
duckdb_disconnect(&con);
duckdb_close(&db);
return 0;
}
Next Steps
C Examples
See complete working code
C++ API
Explore the C++ API