如何通过DuckDB C API提取VARCHAR类型数据?
正确通过DuckDB C API提取VARCHAR类型字符串
在DuckDB 0.8.1的C API中,VARCHAR类型存储为duckdb_string_t结构,该结构采用**小字符串优化(SSO)**机制:
- 当字符串长度≤12字节时,内容直接存入
inlined数组 - 当长度>12字节时,
inlined数组存储的是指向堆中完整字符串的指针(并非压缩内容,你看到的特殊字节是指针的内存表示)
无需手动解析结构字节,DuckDB提供了专门的宏来安全获取字符串内容:
duckdb_string_get_length(str):获取字符串实际长度duckdb_string_get_ptr(str):获取指向字符串内容的const char*指针
修正后的测试代码
// 省略数据库启动、连接及表创建/插入代码(与原代码一致) duckdb_result result; if (duckdb_query(con, "SELECT * FROM strings", &result) == DuckDBError) { fprintf(stderr, "Failed to query database3\n"); goto cleanup; } // 使用data chunk和vector提取数据 duckdb_data_chunk res_chunk = duckdb_result_get_chunk(result, 0); duckdb_vector vec = duckdb_data_chunk_get_vector(res_chunk, 0); duckdb_logical_type type_l = duckdb_vector_get_column_type(vec); duckdb_type type = duckdb_get_type_id(type_l); printf("type id: %d\n", type); // 转换为字符串数组指针 duckdb_string_t *string_array = (duckdb_string_t *)duckdb_vector_get_data(vec); idx_t row_count = duckdb_data_chunk_get_size(res_chunk); // 遍历提取每一行的字符串 for (idx_t i = 0; i < row_count; i++) { duckdb_string_t str = string_array[i]; uint32_t str_len = duckdb_string_get_length(str); const char *str_ptr = duckdb_string_get_ptr(str); printf("Row %llu: length=%u, content='%.*s'\n", i, str_len, str_len, str_ptr); } cleanup: // 清理资源 duckdb_data_chunk_destroy(&res_chunk); duckdb_destroy_result(&result); // 补充数据库断开、销毁等其他清理步骤
预期运行结果
type id: 17 Row 0: length=5, content='aaaaa' Row 1: length=14, content='abcdrfghikjlmn' Row 2: length=12, content='bbbbbbbbbbbb'
注意事项
- 内存管理:
duckdb_string_get_ptr返回的指针由DuckDB托管,无需手动释放,其有效性与对应的duckdb_vector/duckdb_data_chunk生命周期绑定,销毁chunk/vector前可安全访问。 - 空值处理:如果结果包含NULL值,需先通过
duckdb_vector_get_validity获取有效性掩码,判断当前行非NULL后再提取字符串,避免非法内存访问。
内容的提问来源于stack exchange,提问作者yiyang
相关产品推荐
相关产品推荐

