Skip to content

Commit

Permalink
X
Browse files Browse the repository at this point in the history
  • Loading branch information
mewim committed Apr 19, 2023
1 parent 85bc5af commit f068f07
Show file tree
Hide file tree
Showing 3 changed files with 320 additions and 14 deletions.
17 changes: 8 additions & 9 deletions src/c_api/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ kuzu_value* kuzu_node_val_get_property_value_at(kuzu_node_val* node_val, uint64_
}

void kuzu_node_val_add_property(kuzu_node_val* node_val, const char* key, kuzu_value* value) {
auto value_ = std::make_unique<Value>(static_cast<Value*>(value->_value));
auto value_ = std::make_unique<Value>(*static_cast<Value*>(value->_value));
static_cast<NodeVal*>(node_val->_node_val)->addProperty(std::string(key), std::move(value_));
}

Expand Down Expand Up @@ -356,27 +356,26 @@ char* kuzu_rel_val_get_label_name(kuzu_rel_val* rel_val) {
return c_string;
}

uint64_t kuzu_rel_val_get_property_size(kuzu_node_val* node_val) {
return static_cast<NodeVal*>(node_val->_node_val)->getProperties().size();
uint64_t kuzu_rel_val_get_property_size(kuzu_rel_val* rel_val) {
return static_cast<RelVal*>(rel_val->_rel_val)->getProperties().size();
}

char* kuzu_rel_val_get_property_name_at(kuzu_node_val* node_val, uint64_t index) {
auto& name = static_cast<NodeVal*>(node_val->_node_val)->getProperties().at(index).first;
char* kuzu_rel_val_get_property_name_at(kuzu_rel_val* rel_val, uint64_t index) {
auto& name = static_cast<RelVal*>(rel_val->_rel_val)->getProperties().at(index).first;
auto* c_string = (char*)malloc(name.size() + 1);
strcpy(c_string, name.c_str());
return c_string;
}

kuzu_value* kuzu_rel_val_get_property_value_at(kuzu_node_val* node_val, uint64_t index) {
auto& value = static_cast<NodeVal*>(node_val->_node_val)->getProperties().at(index).second;
kuzu_value* kuzu_rel_val_get_property_value_at(kuzu_rel_val* rel_val, uint64_t index) {
auto& value = static_cast<RelVal*>(rel_val->_rel_val)->getProperties().at(index).second;
auto* c_value = (kuzu_value*)malloc(sizeof(kuzu_value));
c_value->_value = value.get();
c_value->_is_owned_by_cpp = true;
return c_value;
}

void kuzu_rel_val_add_property(kuzu_rel_val* rel_val, char* key, kuzu_value* value) {
auto value_ = std::make_unique<Value>(static_cast<Value*>(value->_value));
auto value_ = std::make_unique<Value>(*static_cast<Value*>(value->_value));
static_cast<RelVal*>(rel_val->_rel_val)->addProperty(std::string(key), std::move(value_));
}

Expand Down
10 changes: 5 additions & 5 deletions src/include/c_api/kuzu.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ KUZU_C_API void kuzu_prepared_statement_bind_double(
kuzu_prepared_statement* prepared_statement, char* param_name, double value);
KUZU_C_API void kuzu_prepared_statement_bind_float(
kuzu_prepared_statement* prepared_statement, char* param_name, float value);
// TODO: Bind date_t, timestamp_t, interval_t, and internal_id_t
// TODO: Bind date_t, timestamp_t, interval_t
KUZU_C_API void kuzu_prepared_statement_bind_string(
kuzu_prepared_statement* prepared_statement, char* param_name, char* value);
// TODO: Bind kuzu_value
Expand Down Expand Up @@ -168,7 +168,7 @@ KUZU_C_API kuzu_value* kuzu_value_create_double(double val_);
KUZU_C_API kuzu_value* kuzu_value_create_internal_id(kuzu_internal_id_t val_);
KUZU_C_API kuzu_value* kuzu_value_create_node_val(kuzu_node_val* val_);
KUZU_C_API kuzu_value* kuzu_value_create_rel_val(kuzu_rel_val* val_);
// TODO: Bind date_t, timestamp_t, and internal_id_t
// TODO: Bind date_t, timestamp_t, interval_t
KUZU_C_API kuzu_value* kuzu_value_create_string(char* val_);
KUZU_C_API kuzu_value* kuzu_value_clone(kuzu_value* value);
KUZU_C_API void kuzu_value_copy(kuzu_value* value, kuzu_value* other);
Expand Down Expand Up @@ -211,9 +211,9 @@ KUZU_C_API kuzu_value* kuzu_rel_val_get_dst_id_val(kuzu_rel_val* rel_val);
KUZU_C_API kuzu_internal_id_t kuzu_rel_val_get_src_id(kuzu_rel_val* rel_val);
KUZU_C_API kuzu_internal_id_t kuzu_rel_val_get_dst_id(kuzu_rel_val* rel_val);
KUZU_C_API char* kuzu_rel_val_get_label_name(kuzu_rel_val* rel_val);
KUZU_C_API uint64_t kuzu_rel_val_get_property_size(kuzu_node_val* node_val);
KUZU_C_API char* kuzu_rel_val_get_property_name_at(kuzu_node_val* node_val, uint64_t index);
KUZU_C_API kuzu_value* kuzu_rel_val_get_property_value_at(kuzu_node_val* node_val, uint64_t index);
KUZU_C_API uint64_t kuzu_rel_val_get_property_size(kuzu_rel_val* rel_val);
KUZU_C_API char* kuzu_rel_val_get_property_name_at(kuzu_rel_val* rel_val, uint64_t index);
KUZU_C_API kuzu_value* kuzu_rel_val_get_property_value_at(kuzu_rel_val* rel_val, uint64_t index);
KUZU_C_API void kuzu_rel_val_add_property(kuzu_rel_val* rel_val, char* key, kuzu_value* value);
KUZU_C_API char* kuzu_rel_val_to_string(kuzu_rel_val* rel_val);

Expand Down
307 changes: 307 additions & 0 deletions test/c_api/value_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,41 @@ TEST_F(CApiValueTest, ValueCreateInternalID) {
kuzu_value_destroy(value);
}

TEST_F(CApiValueTest, ValueCreateNodeVal) {
auto internalID = kuzu_internal_id_t{1, 123};
auto nodeVal = kuzu_node_val_create(internalID, (char*)"person");
auto value = kuzu_value_create_node_val(nodeVal);
ASSERT_FALSE(value->_is_owned_by_cpp);
auto cppValue = static_cast<Value*>(value->_value);
ASSERT_EQ(cppValue->getDataType().getTypeID(), DataTypeID::NODE);
auto nodeValCpp = cppValue->getValue<NodeVal>();
ASSERT_EQ(nodeValCpp.getNodeID().tableID, 1);
ASSERT_EQ(nodeValCpp.getNodeID().offset, 123);
ASSERT_EQ(nodeValCpp.getLabelName(), "person");
ASSERT_EQ(nodeValCpp.getProperties().size(), 0);
kuzu_value_destroy(value);
kuzu_node_val_destroy(nodeVal);
}

TEST_F(CApiValueTest, ValueCreateRelVal) {
auto srcID = kuzu_internal_id_t{1, 123};
auto dstID = kuzu_internal_id_t{2, 456};
auto relVal = kuzu_rel_val_create(srcID, dstID, (char*)"knows");
auto value = kuzu_value_create_rel_val(relVal);
ASSERT_FALSE(value->_is_owned_by_cpp);
auto cppValue = static_cast<Value*>(value->_value);
ASSERT_EQ(cppValue->getDataType().getTypeID(), DataTypeID::REL);
auto relValCpp = cppValue->getValue<RelVal>();
ASSERT_EQ(relValCpp.getSrcNodeID().tableID, 1);
ASSERT_EQ(relValCpp.getSrcNodeID().offset, 123);
ASSERT_EQ(relValCpp.getDstNodeID().tableID, 2);
ASSERT_EQ(relValCpp.getDstNodeID().offset, 456);
ASSERT_EQ(relValCpp.getLabelName(), "knows");
ASSERT_EQ(relValCpp.getProperties().size(), 0);
kuzu_value_destroy(value);
kuzu_rel_val_destroy(relVal);
}

TEST_F(CApiValueTest, ValueCreateString) {
kuzu_value* value = kuzu_value_create_string((char*)"abcdefg");
ASSERT_FALSE(value->_is_owned_by_cpp);
Expand Down Expand Up @@ -359,6 +394,53 @@ TEST_F(CApiValueTest, ValueGetDouble) {
kuzu_query_result_destroy(result);
}

TEST_F(CApiValueTest, ValueGetInternalID) {
auto connection = getConnection();
auto result =
kuzu_connection_query(connection, (char*)"MATCH (a:person) RETURN a ORDER BY a.ID");
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_TRUE(value->_is_owned_by_cpp);
auto node = kuzu_value_get_node_val(value);
auto nodeIDVal = kuzu_node_val_get_id_val(node);
auto internalID = kuzu_value_get_internal_id(nodeIDVal);
ASSERT_EQ(internalID.table_id, 0);
ASSERT_EQ(internalID.offset, 0);
kuzu_value_destroy(nodeIDVal);
kuzu_node_val_destroy(node);
kuzu_value_destroy(value);
kuzu_flat_tuple_destroy(flatTuple);
kuzu_query_result_destroy(result);
}

TEST_F(CApiValueTest, ValueGetRelVal) {
auto connection = getConnection();
auto result = kuzu_connection_query(
connection, (char*)"MATCH (a:person) -[r:knows]-> (b:person) RETURN r ORDER BY a.ID, b.ID");
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_TRUE(value->_is_owned_by_cpp);
auto rel = kuzu_value_get_rel_val(value);
auto relSrcID = kuzu_rel_val_get_src_id(rel);
ASSERT_EQ(relSrcID.table_id, 0);
ASSERT_EQ(relSrcID.offset, 0);
auto relDstID = kuzu_rel_val_get_dst_id(rel);
ASSERT_EQ(relDstID.table_id, 0);
ASSERT_EQ(relDstID.offset, 1);
auto relLabel = kuzu_rel_val_get_label_name(rel);
ASSERT_STREQ(relLabel, "knows");
auto propertiesSize = kuzu_rel_val_get_property_size(rel);
ASSERT_EQ(propertiesSize, 5);
free(relLabel);
kuzu_value_destroy(value);
kuzu_flat_tuple_destroy(flatTuple);
kuzu_query_result_destroy(result);
}

TEST_F(CApiValueTest, ValueGetString) {
auto connection = getConnection();
auto result =
Expand Down Expand Up @@ -405,3 +487,228 @@ TEST_F(CApiValueTest, ValueToSting) {
kuzu_flat_tuple_destroy(flatTuple);
kuzu_query_result_destroy(result);
}

TEST_F(CApiValueTest, NodeValClone) {
auto internalID = kuzu_internal_id_t{1, 123};
auto nodeVal = kuzu_node_val_create(internalID, (char*)"person");
auto nodeValClone = kuzu_node_val_clone(nodeVal);
kuzu_node_val_destroy(nodeVal);
auto nodeValCpp = (NodeVal*)nodeValClone->_node_val;
ASSERT_EQ(nodeValCpp->getNodeID().tableID, 1);
ASSERT_EQ(nodeValCpp->getNodeID().offset, 123);
ASSERT_EQ(nodeValCpp->getLabelName(), "person");
ASSERT_EQ(nodeValCpp->getProperties().size(), 0);
kuzu_node_val_destroy(nodeValClone);
}

TEST_F(CApiValueTest, NodeValGetLabelVal) {
auto internalID = kuzu_internal_id_t{1, 123};
auto nodeVal = kuzu_node_val_create(internalID, (char*)"person");
auto value = kuzu_value_create_node_val(nodeVal);
auto labelVal = kuzu_node_val_get_label_val(nodeVal);
auto labelStr = kuzu_value_get_string(labelVal);
ASSERT_STREQ(labelStr, "person");
free(labelStr);
kuzu_value_destroy(labelVal);
kuzu_value_destroy(value);
kuzu_node_val_destroy(nodeVal);
}

TEST_F(CApiValueTest, NodeValGetID) {
auto internalID = kuzu_internal_id_t{1, 123};
auto nodeVal = kuzu_node_val_create(internalID, (char*)"person");
auto value = kuzu_value_create_node_val(nodeVal);
auto nodeID = kuzu_node_val_get_id(nodeVal);
ASSERT_EQ(nodeID.table_id, 1);
ASSERT_EQ(nodeID.offset, 123);
kuzu_value_destroy(value);
kuzu_node_val_destroy(nodeVal);
}

TEST_F(CApiValueTest, NodeValGetLabelName) {
auto internalID = kuzu_internal_id_t{1, 123};
auto nodeVal = kuzu_node_val_create(internalID, (char*)"person");
auto value = kuzu_value_create_node_val(nodeVal);
auto labelName = kuzu_node_val_get_label_name(nodeVal);
ASSERT_STREQ(labelName, "person");
free(labelName);
kuzu_value_destroy(value);
kuzu_node_val_destroy(nodeVal);
}

TEST_F(CApiValueTest, NodeValAddProperty) {
auto internalID = kuzu_internal_id_t{1, 123};
auto nodeVal = kuzu_node_val_create(internalID, (char*)"person");
auto propertySize = kuzu_node_val_get_property_size(nodeVal);
ASSERT_EQ(propertySize, 0);

auto propertyKey = (char*)"fName";
auto propertyValue = kuzu_value_create_string((char*)"Alice");
kuzu_node_val_add_property(nodeVal, propertyKey, propertyValue);
propertySize = kuzu_node_val_get_property_size(nodeVal);
ASSERT_EQ(propertySize, 1);
kuzu_value_destroy(propertyValue);

propertyKey = (char*)"age";
propertyValue = kuzu_value_create_int64(10);
kuzu_node_val_add_property(nodeVal, propertyKey, propertyValue);
propertySize = kuzu_node_val_get_property_size(nodeVal);
ASSERT_EQ(propertySize, 2);
kuzu_value_destroy(propertyValue);

kuzu_node_val_destroy(nodeVal);
}

TEST_F(CApiValueTest, NodeValGetProperty) {
auto connection = getConnection();
auto result =
kuzu_connection_query(connection, (char*)"MATCH (a:person) RETURN a ORDER BY a.ID");
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_TRUE(value->_is_owned_by_cpp);
auto node = kuzu_value_get_node_val(value);
auto propertyName = kuzu_node_val_get_property_name_at(node, 0);
ASSERT_STREQ(propertyName, "ID");
free(propertyName);
propertyName = kuzu_node_val_get_property_name_at(node, 1);
ASSERT_STREQ(propertyName, "fName");
free(propertyName);
propertyName = kuzu_node_val_get_property_name_at(node, 2);
ASSERT_STREQ(propertyName, "gender");
free(propertyName);
propertyName = kuzu_node_val_get_property_name_at(node, 3);
ASSERT_STREQ(propertyName, "isStudent");
free(propertyName);

auto propertyValue = kuzu_node_val_get_property_value_at(node, 0);
auto propertyValueID = kuzu_value_get_int64(propertyValue);
ASSERT_EQ(propertyValueID, 0);
kuzu_value_destroy(propertyValue);
propertyValue = kuzu_node_val_get_property_value_at(node, 1);
auto propertyValuefName = kuzu_value_get_string(propertyValue);
ASSERT_STREQ(propertyValuefName, "Alice");
free(propertyValuefName);
kuzu_value_destroy(propertyValue);
propertyValue = kuzu_node_val_get_property_value_at(node, 2);
auto propertyValueGender = kuzu_value_get_int64(propertyValue);
ASSERT_EQ(propertyValueGender, 1);
kuzu_value_destroy(propertyValue);
propertyValue = kuzu_node_val_get_property_value_at(node, 3);
auto propertyValueIsStudent = kuzu_value_get_bool(propertyValue);
ASSERT_EQ(propertyValueIsStudent, true);
kuzu_value_destroy(propertyValue);

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

TEST_F(CApiValueTest, NodeValToString) {
auto internalID = kuzu_internal_id_t{1, 123};
auto nodeVal = kuzu_node_val_create(internalID, (char*)"person");

auto propertyKey = (char*)"fName";
auto propertyValue = kuzu_value_create_string((char*)"Smith");
kuzu_node_val_add_property(nodeVal, propertyKey, propertyValue);
kuzu_value_destroy(propertyValue);

propertyKey = (char*)"age";
propertyValue = kuzu_value_create_int64(10);
kuzu_node_val_add_property(nodeVal, propertyKey, propertyValue);
kuzu_value_destroy(propertyValue);

auto str = kuzu_node_val_to_string(nodeVal);
ASSERT_STREQ(str, "(label:person, 1:123, {fName:Smith, age:10})");
free(str);
kuzu_node_val_destroy(nodeVal);
}

TEST_F(CApiValueTest, RelValClone) {
auto srcID = kuzu_internal_id_t{1, 123};
auto dstID = kuzu_internal_id_t{2, 456};
auto relVal = kuzu_rel_val_create(srcID, dstID, (char*)"knows");
auto relValClone = kuzu_rel_val_clone(relVal);
auto srcIDVal = kuzu_rel_val_get_src_id_val(relValClone);
auto dstIDVal = kuzu_rel_val_get_dst_id_val(relValClone);
auto srcIDClone = kuzu_value_get_internal_id(srcIDVal);
auto dstIDClone = kuzu_value_get_internal_id(dstIDVal);
ASSERT_EQ(srcIDClone.table_id, srcID.table_id);
ASSERT_EQ(srcIDClone.offset, srcID.offset);
ASSERT_EQ(dstIDClone.table_id, dstID.table_id);
ASSERT_EQ(dstIDClone.offset, dstID.offset);
auto labelName = kuzu_rel_val_get_label_name(relValClone);
ASSERT_STREQ(labelName, "knows");
auto propertySize = kuzu_rel_val_get_property_size(relValClone);
ASSERT_EQ(propertySize, 0);
free(labelName);
kuzu_value_destroy(srcIDVal);
kuzu_value_destroy(dstIDVal);
kuzu_rel_val_destroy(relValClone);
}

TEST_F(CApiValueTest, RelValAddAndGetProperty) {
auto srcID = kuzu_internal_id_t{1, 123};
auto dstID = kuzu_internal_id_t{2, 456};
auto relVal = kuzu_rel_val_create(srcID, dstID, (char*)"knows");
auto propertySize = kuzu_rel_val_get_property_size(relVal);
ASSERT_EQ(propertySize, 0);

auto propertyKey = (char*)"fName";
auto propertyValue = kuzu_value_create_string((char*)"Alice");
kuzu_rel_val_add_property(relVal, propertyKey, propertyValue);
propertySize = kuzu_rel_val_get_property_size(relVal);
ASSERT_EQ(propertySize, 1);
kuzu_value_destroy(propertyValue);

propertyKey = (char*)"age";
propertyValue = kuzu_value_create_int64(10);
kuzu_rel_val_add_property(relVal, propertyKey, propertyValue);
propertySize = kuzu_rel_val_get_property_size(relVal);
ASSERT_EQ(propertySize, 2);
kuzu_value_destroy(propertyValue);

propertyKey = kuzu_rel_val_get_property_name_at(relVal, 0);
ASSERT_STREQ(propertyKey, "fName");
free(propertyKey);

propertyKey = kuzu_rel_val_get_property_name_at(relVal, 1);
ASSERT_STREQ(propertyKey, "age");
free(propertyKey);

propertyValue = kuzu_rel_val_get_property_value_at(relVal, 0);
auto propertyValuefName = kuzu_value_get_string(propertyValue);
ASSERT_STREQ(propertyValuefName, "Alice");
kuzu_value_destroy(propertyValue);
free(propertyValuefName);

propertyValue = kuzu_rel_val_get_property_value_at(relVal, 1);
auto propertyValueAge = kuzu_value_get_int64(propertyValue);
ASSERT_EQ(propertyValueAge, 10);
kuzu_value_destroy(propertyValue);

kuzu_rel_val_destroy(relVal);
}

TEST_F(CApiValueTest, RelValToString) {
auto srcID = kuzu_internal_id_t{1, 123};
auto dstID = kuzu_internal_id_t{2, 456};
auto relVal = kuzu_rel_val_create(srcID, dstID, (char*)"knows");

auto propertyKey = (char*)"fName";
auto propertyValue = kuzu_value_create_string((char*)"Alice");
kuzu_rel_val_add_property(relVal, propertyKey, propertyValue);
kuzu_value_destroy(propertyValue);

propertyKey = (char*)"age";
propertyValue = kuzu_value_create_int64(10);
kuzu_rel_val_add_property(relVal, propertyKey, propertyValue);
kuzu_value_destroy(propertyValue);

auto str = kuzu_rel_val_to_string(relVal);
ASSERT_STREQ(str, "(1:123)-[label:knows, {fName:Alice, age:10}]->(2:456)");

kuzu_rel_val_destroy(relVal);
}

0 comments on commit f068f07

Please sign in to comment.