Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add struct binding for C API #1531

Merged
merged 1 commit into from
May 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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