Skip to content

Commit

Permalink
Merge pull request #1531 from kuzudb/c-api-struct-binding
Browse files Browse the repository at this point in the history
Add struct binding for C API
  • Loading branch information
mewim committed May 11, 2023
2 parents 1d45b99 + 2bf6131 commit 4c2ac16
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/c_api/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,27 @@ kuzu_value* kuzu_value_get_list_element(kuzu_value* value, uint64_t index) {
return c_value;
}

uint64_t kuzu_value_get_struct_num_fields(kuzu_value* value) {
auto val = static_cast<Value*>(value->_value);
auto data_type = val->getDataType();
auto struct_type_info = reinterpret_cast<StructTypeInfo*>(data_type.getExtraTypeInfo());
return struct_type_info->getStructFields().size();
}

char* kuzu_value_get_struct_field_name(kuzu_value* value, uint64_t index) {
auto val = static_cast<Value*>(value->_value);
auto data_type = val->getDataType();
auto struct_type_info = reinterpret_cast<StructTypeInfo*>(data_type.getExtraTypeInfo());
auto struct_field_name = struct_type_info->getStructFields()[index]->getName();
auto* c_struct_field_name = (char*)malloc(sizeof(char) * (struct_field_name.size() + 1));
strcpy(c_struct_field_name, struct_field_name.c_str());
return c_struct_field_name;
}

kuzu_value* kuzu_value_get_struct_field_value(kuzu_value* value, uint64_t index) {
return kuzu_value_get_list_element(value, index);
}

kuzu_data_type* kuzu_value_get_data_type(kuzu_value* value) {
auto* c_data_type = (kuzu_data_type*)malloc(sizeof(kuzu_data_type));
c_data_type->_data_type = new DataType(static_cast<Value*>(value->_value)->getDataType());
Expand Down
4 changes: 4 additions & 0 deletions src/include/c_api/kuzu.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ KUZU_C_API typedef enum {
INTERNAL_ID = 40,
STRING = 50,
VAR_LIST = 52,
STRUCT = 53,
} kuzu_data_type_id;

// Database
Expand Down Expand Up @@ -198,6 +199,9 @@ KUZU_C_API void kuzu_value_copy(kuzu_value* value, kuzu_value* other);
KUZU_C_API void kuzu_value_destroy(kuzu_value* value);
KUZU_C_API uint64_t kuzu_value_get_list_size(kuzu_value* value);
KUZU_C_API kuzu_value* kuzu_value_get_list_element(kuzu_value* value, uint64_t index);
KUZU_C_API uint64_t kuzu_value_get_struct_num_fields(kuzu_value* value);
KUZU_C_API char* kuzu_value_get_struct_field_name(kuzu_value* value, uint64_t index);
KUZU_C_API kuzu_value* kuzu_value_get_struct_field_value(kuzu_value* value, uint64_t index);
KUZU_C_API kuzu_data_type* kuzu_value_get_data_type(kuzu_value* value);
KUZU_C_API bool kuzu_value_get_bool(kuzu_value* value);
KUZU_C_API int16_t kuzu_value_get_int16(kuzu_value* value);
Expand Down
88 changes: 88 additions & 0 deletions test/c_api/value_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,94 @@ TEST_F(CApiValueTest, GetListElement) {
kuzu_query_result_destroy(result);
}

TEST_F(CApiValueTest, GetStructNumFields) {
auto connection = getConnection();
auto result = kuzu_connection_query(
connection, (char*)"MATCH (m:movies) WHERE m.name=\"Roma\" RETURN m.description");
ASSERT_TRUE(kuzu_query_result_is_success(result));
ASSERT_TRUE(kuzu_query_result_has_next(result));
auto flatTuple = kuzu_query_result_get_next(result);
auto value = kuzu_flat_tuple_get_value(flatTuple, 0);
ASSERT_EQ(kuzu_value_get_struct_num_fields(value), 4);

kuzu_value_destroy(value);
kuzu_flat_tuple_destroy(flatTuple);
kuzu_query_result_destroy(result);
}

TEST_F(CApiValueTest, GetStructFieldName) {
auto connection = getConnection();
auto result = kuzu_connection_query(
connection, (char*)"MATCH (m:movies) WHERE m.name=\"Roma\" RETURN m.description");
ASSERT_TRUE(kuzu_query_result_is_success(result));
ASSERT_TRUE(kuzu_query_result_has_next(result));
auto flatTuple = kuzu_query_result_get_next(result);
auto value = kuzu_flat_tuple_get_value(flatTuple, 0);
auto fieldName = kuzu_value_get_struct_field_name(value, 0);
ASSERT_STREQ(fieldName, "RATING");
free(fieldName);

fieldName = kuzu_value_get_struct_field_name(value, 1);
ASSERT_STREQ(fieldName, "VIEWS");
free(fieldName);

fieldName = kuzu_value_get_struct_field_name(value, 2);
ASSERT_STREQ(fieldName, "RELEASE");
free(fieldName);

fieldName = kuzu_value_get_struct_field_name(value, 3);
ASSERT_STREQ(fieldName, "FILM");
free(fieldName);

kuzu_value_destroy(value);
kuzu_flat_tuple_destroy(flatTuple);
kuzu_query_result_destroy(result);
}

TEST_F(CApiValueTest, GetStructFieldValue) {
auto connection = getConnection();
auto result = kuzu_connection_query(
connection, (char*)"MATCH (m:movies) WHERE m.name=\"Roma\" RETURN m.description");
ASSERT_TRUE(kuzu_query_result_is_success(result));
ASSERT_TRUE(kuzu_query_result_has_next(result));
auto flatTuple = kuzu_query_result_get_next(result);
auto value = kuzu_flat_tuple_get_value(flatTuple, 0);

auto fieldValue = kuzu_value_get_struct_field_value(value, 0);
auto fieldType = kuzu_value_get_data_type(fieldValue);
ASSERT_EQ(kuzu_data_type_get_id(fieldType), DataTypeID::DOUBLE);
ASSERT_DOUBLE_EQ(kuzu_value_get_double(fieldValue), 1223);
kuzu_data_type_destroy(fieldType);
kuzu_value_destroy(fieldValue);

fieldValue = kuzu_value_get_struct_field_value(value, 1);
fieldType = kuzu_value_get_data_type(fieldValue);
ASSERT_EQ(kuzu_data_type_get_id(fieldType), DataTypeID::INT64);
ASSERT_EQ(kuzu_value_get_int64(fieldValue), 10003);
kuzu_data_type_destroy(fieldType);
kuzu_value_destroy(fieldValue);

fieldValue = kuzu_value_get_struct_field_value(value, 2);
fieldType = kuzu_value_get_data_type(fieldValue);
ASSERT_EQ(kuzu_data_type_get_id(fieldType), DataTypeID::TIMESTAMP);
auto timestamp = kuzu_value_get_timestamp(fieldValue);
ASSERT_EQ(timestamp.value, 1297442662000000);
kuzu_data_type_destroy(fieldType);
kuzu_value_destroy(fieldValue);

fieldValue = kuzu_value_get_struct_field_value(value, 3);
fieldType = kuzu_value_get_data_type(fieldValue);
ASSERT_EQ(kuzu_data_type_get_id(fieldType), DataTypeID::DATE);
auto date = kuzu_value_get_date(fieldValue);
ASSERT_EQ(date.days, 15758);
kuzu_data_type_destroy(fieldType);
kuzu_value_destroy(fieldValue);

kuzu_value_destroy(value);
kuzu_flat_tuple_destroy(flatTuple);
kuzu_query_result_destroy(result);
}

TEST_F(CApiValueTest, GetDataType) {
auto connection = getConnection();
auto result = kuzu_connection_query(
Expand Down

0 comments on commit 4c2ac16

Please sign in to comment.