쿼리
쿼리 (Query, C API)
duckdb_query 메서드는 C에서 DuckDB에 SQL 쿼리를 실행할 수 있게 해줘요. 이 메서드는 두 파라미터를 받아요: (null-종료된) SQL 쿼리 문자열과 duckdb_result 결과 포인터. 애플리케이션이 결과 집합에 관심이 없거나 쿼리가 결과를 생성하지 않으면 결과 포인터는 NULL일 수 있어요. 결과를 소비한 뒤에는 duckdb_destroy_result 메서드로 결과를 정리해야 해요.
duckdb_result 객체에서 다양한 메서드로 요소를 추출할 수 있어요. duckdb_column_count로 컬럼 수를 추출할 수 있어요. duckdb_column_name과 duckdb_column_type으로 개별 컬럼의 이름과 타입을 추출할 수 있어요.
출처: 문서
본문
예시
duckdb_state state;
duckdb_result result;
// 테이블 생성
state = duckdb_query(con, "CREATE TABLE integers (i INTEGER, j INTEGER);", NULL);
if (state == DuckDBError) {
// 오류 처리
}
// 테이블에 세 행 삽입
state = duckdb_query(con, "INSERT INTO integers VALUES (3, 4), (5, 6), (7, NULL);", NULL);
if (state == DuckDBError) {
// 오류 처리
}
// 행 다시 쿼리
state = duckdb_query(con, "SELECT * FROM integers", &result);
if (state == DuckDBError) {
// 오류 처리
}
// 결과 처리
// ...
// 처리를 마친 후 결과 파괴
duckdb_destroy_result(&result);
값 추출 (Value Extraction)
값은 duckdb_fetch_chunk 함수나 duckdb_value 편의 함수를 사용해 추출할 수 있어요. duckdb_fetch_chunk 함수는 DuckDB의 네이티브 배열 형식으로 데이터 청크를 직접 건네주므로 매우 빠를 수 있어요. duckdb_value 함수들은 경계(bounds) 및 타입 검사를 수행하고, 값을 원하는 타입으로 자동 캐스트해요. 이로 인해 더 편리하고 사용하기 쉬워지는 대신 느려요.
자세한 내용은 [Types]({% link docs/current/clients/c/types.md %}) 페이지를 참고해요.
최적의 성능을 위해
duckdb_fetch_chunk를 사용해 쿼리 결과에서 데이터를 추출해요.duckdb_value함수들은 내부 타입 검사, 경계 검사, 캐스팅을 수행하므로 더 느려요.
duckdb_fetch_chunk
아래는 duckdb_fetch_chunk 함수로 위 결과를 CSV 형식으로 인쇄하는 end-to-end 예시예요.
이 함수는 일반적(generic)이지 않다는 점을 주목해요: 결과 컬럼의 타입이 정확히 무엇인지 알아야 해요.
duckdb_database db;
duckdb_connection con;
duckdb_open(nullptr, &db);
duckdb_connect(db, &con);
duckdb_result res;
duckdb_query(con, "CREATE TABLE integers (i INTEGER, j INTEGER);", NULL);
duckdb_query(con, "INSERT INTO integers VALUES (3, 4), (5, 6), (7, NULL);", NULL);
duckdb_query(con, "SELECT * FROM integers;", &res);
// 결과가 소진될 때까지 반복
while (true) {
duckdb_data_chunk result = duckdb_fetch_chunk(res);
if (!result) {
// 결과 소진됨
break;
}
// 데이터 청크에서 행 수 얻기
idx_t row_count = duckdb_data_chunk_get_size(result);
// 첫 번째 컬럼 얻기
duckdb_vector col1 = duckdb_data_chunk_get_vector(result, 0);
int32_t *col1_data = (int32_t *) duckdb_vector_get_data(col1);
uint64_t *col1_validity = duckdb_vector_get_validity(col1);
// 두 번째 컬럼 얻기
duckdb_vector col2 = duckdb_data_chunk_get_vector(result, 1);
int32_t *col2_data = (int32_t *) duckdb_vector_get_data(col2);
uint64_t *col2_validity = duckdb_vector_get_validity(col2);
// 행 반복
for (idx_t row = 0; row < row_count; row++) {
if (duckdb_validity_row_is_valid(col1_validity, row)) {
printf("%d", col1_data[row]);
} else {
printf("NULL");
}
printf(",");
if (duckdb_validity_row_is_valid(col2_validity, row)) {
printf("%d", col2_data[row]);
} else {
printf("NULL");
}
printf("\n");
}
duckdb_destroy_data_chunk(&result);
}
// 정리
duckdb_destroy_result(&res);
duckdb_disconnect(&con);
duckdb_close(&db);
이것은 다음 결과를 인쇄해요:
3,4
5,6
7,NULL
duckdb_value
Deprecated:
duckdb_value함수들은 deprecated이며 향후 릴리스에서 제거될 예정이에요.
아래는 duckdb_value_varchar 함수로 위 결과를 CSV 형식으로 인쇄하는 예시예요.
이 함수는 일반적(generic)이므로 개별 결과 컬럼의 타입을 알 필요가 없어요.
// `duckdb_value_varchar`로 위 결과를 CSV 형식으로 인쇄
idx_t row_count = duckdb_row_count(&result);
idx_t column_count = duckdb_column_count(&result);
for (idx_t row = 0; row < row_count; row++) {
for (idx_t col = 0; col < column_count; col++) {
if (col > 0) printf(",");
auto str_val = duckdb_value_varchar(&result, col, row);
printf("%s", str_val);
duckdb_free(str_val);
}
printf("\n");
}
API 참조 개요
duckdb_state duckdb_query(duckdb_connection connection, const char *query, duckdb_result *out_result);
void duckdb_destroy_result(duckdb_result *result);
const char *duckdb_column_name(duckdb_result *result, idx_t col);
duckdb_type duckdb_column_type(duckdb_result *result, idx_t col);
duckdb_statement_type duckdb_result_statement_type(duckdb_result result);
duckdb_logical_type duckdb_column_logical_type(duckdb_result *result, idx_t col);
duckdb_arrow_options duckdb_result_get_arrow_options(duckdb_result *result);
idx_t duckdb_column_count(duckdb_result *result);
idx_t duckdb_row_count(duckdb_result *result);
idx_t duckdb_rows_changed(duckdb_result *result);
void *duckdb_column_data(duckdb_result *result, idx_t col);
bool *duckdb_nullmask_data(duckdb_result *result, idx_t col);
const char *duckdb_result_error(duckdb_result *result);
duckdb_error_type duckdb_result_error_type(duckdb_result *result);
duckdb_query
연결 안에서 SQL 쿼리를 실행하고 전체(물리화된) 결과를 out_result 포인터에 저장해요.
쿼리 실행에 실패하면 DuckDBError가 반환되고 duckdb_result_error를 호출해 오류 메시지를 검색할 수 있어요.
duckdb_query 실행 후에는 쿼리가 실패하더라도 결과 객체에 duckdb_destroy_result를 호출해야 한다는 점을 주목해요. 그렇지 않으면 결과 안에 저장된 오류가 올바르게 해제되지 않아요.
문법
duckdb_state duckdb_query(
duckdb_connection connection,
const char *query,
duckdb_result *out_result
);
파라미터
connection: 쿼리를 수행할 연결.query: 실행할 SQL 쿼리.out_result: 쿼리 결과.
반환 값
성공 시 DuckDBSuccess, 실패 시 DuckDBError.
duckdb_destroy_result
결과를 닫고 그 결과에 할당된 모든 메모리를 해제해요.
문법
void duckdb_destroy_result(
duckdb_result *result
);
파라미터
result: 파괴할 결과.
duckdb_column_name
지정된 컬럼의 이름을 반환해요. 결과를 해제할 필요는 없어요. 컬럼 이름은 결과가 파괴될 때 자동으로 파괴돼요.
컬럼이 범위를 벗어나면 NULL을 반환해요.
문법
const char *duckdb_column_name(
duckdb_result *result,
idx_t col
);
파라미터
result: 컬럼 이름을 가져올 결과 객체.col: 컬럼 인덱스.
반환 값
지정된 컬럼의 이름.
duckdb_column_type
지정된 컬럼의 컬럼 타입을 반환해요.
컬럼이 범위를 벗어나면 DUCKDB_TYPE_INVALID를 반환해요.
문법
duckdb_type duckdb_column_type(
duckdb_result *result,
idx_t col
);
파라미터
result: 컬럼 타입을 가져올 결과 객체.col: 컬럼 인덱스.
반환 값
지정된 컬럼의 컬럼 타입.
duckdb_result_statement_type
실행된 statement의 statement 타입을 반환해요
문법
duckdb_statement_type duckdb_result_statement_type(
duckdb_result result
);
파라미터
result: statement 타입을 가져올 결과 객체.
반환 값
duckdb_statement_type 값 또는 DUCKDB_STATEMENT_TYPE_INVALID
duckdb_column_logical_type
지정된 컬럼의 논리 컬럼 타입을 반환해요.
이 호출의 반환 타입은 duckdb_destroy_logical_type으로 파괴해야 해요.
컬럼이 범위를 벗어나면 NULL을 반환해요.
문법
duckdb_logical_type duckdb_column_logical_type(
duckdb_result *result,
idx_t col
);
파라미터
result: 컬럼 타입을 가져올 결과 객체.col: 컬럼 인덱스.
반환 값
지정된 컬럼의 논리 컬럼 타입.
duckdb_result_get_arrow_options
주어진 결과와 연관된 arrow 옵션을 반환해요. 이 옵션들은 arrow 배열/스키마가 어떻게 생성돼야 하는지에 대한 정의예요.
문법
duckdb_arrow_options duckdb_result_get_arrow_options(
duckdb_result *result
);
파라미터
result: arrow 옵션을 가져올 결과 객체.
반환 값
주어진 결과와 연관된 arrow 옵션. 이것은 duckdb_destroy_arrow_options로 파괴해야 해요.
duckdb_column_count
결과 객체에 존재하는 컬럼 수를 반환해요.
문법
idx_t duckdb_column_count(
duckdb_result *result
);
파라미터
result: 결과 객체.
반환 값
결과 객체에 존재하는 컬럼 수.
duckdb_row_count
경고: Deprecation 공지. 이 메서드는 향후 릴리스에서 제거될 예정이에요.
결과 객체에 존재하는 행 수를 반환해요.
문법
idx_t duckdb_row_count(
duckdb_result *result
);
파라미터
result: 결과 객체.
반환 값
결과 객체에 존재하는 행 수.
duckdb_rows_changed
결과에 저장된 쿼리에 의해 변경된 행 수를 반환해요. 이는 INSERT/UPDATE/DELETE 쿼리에만 관련돼요. 다른 쿼리의 경우 rows_changed는 0이에요.
문법
idx_t duckdb_rows_changed(
duckdb_result *result
);
파라미터
result: 결과 객체.
반환 값
변경된 행 수.
duckdb_column_data
Deprecated: 이 메서드는 deprecated예요.
duckdb_result_get_chunk를 사용하는 것을 선호해요.
열 지향 형식으로 결과의 특정 컬럼 데이터를 반환해요.
이 함수는 결과 데이터를 포함하는 밀집(dense) 배열을 반환해요. 배열에 저장된 정확한 타입은 해당 duckdb_type(duckdb_column_type이 제공)에 따라 달라져요. 데이터가 접근되어야 하는 정확한 타입에 대해서는 the types section의 주석이나 DUCKDB_TYPE 열거형을 참고해요.
예를 들어 DUCKDB_TYPE_INTEGER 타입 컬럼의 경우 행을 다음과 같이 접근할 수 있어요:
int32_t *data = (int32_t *) duckdb_column_data(&result, 0);
printf("Data for row %d: %d\n", row, data[row]);
문법
void *duckdb_column_data(
duckdb_result *result,
idx_t col
);
파라미터
result: 컬럼 데이터를 가져올 결과 객체.col: 컬럼 인덱스.
반환 값
지정된 컬럼의 컬럼 데이터.
duckdb_nullmask_data
Deprecated: 이 메서드는 deprecated예요.
duckdb_result_get_chunk를 사용하는 것을 선호해요.
열 지향 형식으로 결과의 특정 컬럼의 nullmask를 반환해요. nullmask는 각 행이 NULL인지 여부를 나타내요. 행이 NULL이면 duckdb_column_data가 제공하는 배열에 존재하는 값은 정의되지 않아요.
int32_t *data = (int32_t *) duckdb_column_data(&result, 0);
bool *nullmask = duckdb_nullmask_data(&result, 0);
if (nullmask[row]) {
printf("Data for row %d: NULL\n", row);
} else {
printf("Data for row %d: %d\n", row, data[row]);
}
문법
bool *duckdb_nullmask_data(
duckdb_result *result,
idx_t col
);
파라미터
result: nullmask를 가져올 결과 객체.col: 컬럼 인덱스.
반환 값
지정된 컬럼의 nullmask.
duckdb_result_error
결과에 포함된 오류 메시지를 반환해요. 오류는 duckdb_query가 DuckDBError를 반환할 때만 설정돼요.
이 함수의 결과를 해제해서는 안 됩니다. duckdb_destroy_result가 호출될 때 정리돼요.
문법
const char *duckdb_result_error(
duckdb_result *result
);
파라미터
result: 오류를 가져올 결과 객체.
반환 값
결과의 오류.
duckdb_result_error_type
결과에 포함된 결과 오류 타입을 반환해요. 오류는 duckdb_query가 DuckDBError를 반환할 때만 설정돼요.
문법
duckdb_error_type duckdb_result_error_type(
duckdb_result *result
);
파라미터
result: 오류를 가져올 결과 객체.
반환 값
결과의 오류 타입.
더 알아보기 (Learn more)
C API의 타입 지원에 대한 자세한 내용은 [Types]({% link docs/current/clients/c/types.md %}) 문서를 참고해요.