Skip to content

Commit

Permalink
Merge pull request #2153 from kuzudb/api-tests
Browse files Browse the repository at this point in the history
Link C and C++ API tests against the API-restricted shared library
  • Loading branch information
benjaminwinger committed Oct 12, 2023
2 parents 96b3f7e + e0507dd commit 10233ad
Show file tree
Hide file tree
Showing 37 changed files with 632 additions and 436 deletions.
18 changes: 14 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ set(CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS TRUE)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if (MSVC)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
endif()
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)

# Detect OS and architecture, copied from DuckDB
set(OS_NAME "unknown")
Expand Down Expand Up @@ -92,6 +90,9 @@ if(MSVC)
# Remove the default to avoid warnings
STRING(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
STRING(REPLACE "/EHs" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
# Store all libraries and binaries in the same directory so that kuzu_shared.dll is found at runtime
set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/src")
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/src")
endif()
if(CMAKE_BUILD_TYPE MATCHES Release)
if(MSVC)
Expand Down Expand Up @@ -152,6 +153,15 @@ function(add_kuzu_test TEST_NAME)
gtest_discover_tests(${TEST_NAME} DISCOVERY_TIMEOUT 600 DISCOVERY_MODE PRE_TEST)
endfunction()

function(add_kuzu_api_test TEST_NAME)
set(SRCS ${ARGN})
add_executable(${TEST_NAME} ${SRCS})
target_link_libraries(${TEST_NAME} PRIVATE api_graph_test api_test_helper)
target_include_directories(${TEST_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/test/include)
include(GoogleTest)
gtest_discover_tests(${TEST_NAME})
endfunction()

add_definitions(-DKUZU_ROOT_DIRECTORY="${PROJECT_SOURCE_DIR}")
add_definitions(-DKUZU_STORAGE_VERSION="${CMAKE_PROJECT_VERSION}")

Expand Down
1 change: 0 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ target_include_directories(kuzu_shared
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

include(GenerateExportHeader)
generate_export_header(kuzu_shared BASE_NAME kuzu EXPORT_MACRO_NAME KUZU_API STATIC_DEFINE KUZU_STATIC_DEFINE)
target_include_directories(kuzu PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(kuzu_shared PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_compile_definitions(kuzu PUBLIC KUZU_STATIC_DEFINE)
8 changes: 8 additions & 0 deletions src/common/types/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,14 @@ void StructTypeInfo::serializeInternal(FileInfo* fileInfo, uint64_t& offset) con
SerDeser::serializeVectorOfPtrs(fields, fileInfo, offset);
}

LogicalType::LogicalType(LogicalTypeID typeID) : typeID{typeID}, extraTypeInfo{nullptr} {
setPhysicalType();
};
LogicalType::LogicalType(LogicalTypeID typeID, std::unique_ptr<ExtraTypeInfo> extraTypeInfo)
: typeID{typeID}, extraTypeInfo{std::move(extraTypeInfo)} {
setPhysicalType();
};

LogicalType::LogicalType(const LogicalType& other) {
typeID = other.typeID;
physicalType = other.physicalType;
Expand Down
36 changes: 20 additions & 16 deletions src/common/vector/value_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,22 +372,22 @@ void ArrowColumnVector::slice(ValueVector* vector, offset_t offset) {
setArrowColumn(vector, arrowColumnBuffer->column->Slice((int64_t)offset));
}

template void ValueVector::setValue<nodeID_t>(uint32_t pos, nodeID_t val);
template void ValueVector::setValue<bool>(uint32_t pos, bool val);
template void ValueVector::setValue<int64_t>(uint32_t pos, int64_t val);
template void ValueVector::setValue<int32_t>(uint32_t pos, int32_t val);
template void ValueVector::setValue<int16_t>(uint32_t pos, int16_t val);
template void ValueVector::setValue<int8_t>(uint32_t pos, int8_t val);
template void ValueVector::setValue<uint64_t>(uint32_t pos, uint64_t val);
template void ValueVector::setValue<uint32_t>(uint32_t pos, uint32_t val);
template void ValueVector::setValue<uint16_t>(uint32_t pos, uint16_t val);
template void ValueVector::setValue<uint8_t>(uint32_t pos, uint8_t val);
template void ValueVector::setValue<double_t>(uint32_t pos, double_t val);
template void ValueVector::setValue<float_t>(uint32_t pos, float_t val);
template void ValueVector::setValue<date_t>(uint32_t pos, date_t val);
template void ValueVector::setValue<timestamp_t>(uint32_t pos, timestamp_t val);
template void ValueVector::setValue<interval_t>(uint32_t pos, interval_t val);
template void ValueVector::setValue<list_entry_t>(uint32_t pos, list_entry_t val);
template KUZU_API void ValueVector::setValue<nodeID_t>(uint32_t pos, nodeID_t val);
template KUZU_API void ValueVector::setValue<bool>(uint32_t pos, bool val);
template KUZU_API void ValueVector::setValue<int64_t>(uint32_t pos, int64_t val);
template KUZU_API void ValueVector::setValue<int32_t>(uint32_t pos, int32_t val);
template KUZU_API void ValueVector::setValue<int16_t>(uint32_t pos, int16_t val);
template KUZU_API void ValueVector::setValue<int8_t>(uint32_t pos, int8_t val);
template KUZU_API void ValueVector::setValue<uint64_t>(uint32_t pos, uint64_t val);
template KUZU_API void ValueVector::setValue<uint32_t>(uint32_t pos, uint32_t val);
template KUZU_API void ValueVector::setValue<uint16_t>(uint32_t pos, uint16_t val);
template KUZU_API void ValueVector::setValue<uint8_t>(uint32_t pos, uint8_t val);
template KUZU_API void ValueVector::setValue<double_t>(uint32_t pos, double_t val);
template KUZU_API void ValueVector::setValue<float_t>(uint32_t pos, float_t val);
template KUZU_API void ValueVector::setValue<date_t>(uint32_t pos, date_t val);
template KUZU_API void ValueVector::setValue<timestamp_t>(uint32_t pos, timestamp_t val);
template KUZU_API void ValueVector::setValue<interval_t>(uint32_t pos, interval_t val);
template KUZU_API void ValueVector::setValue<list_entry_t>(uint32_t pos, list_entry_t val);

template<>
void ValueVector::setValue(uint32_t pos, ku_string_t val) {
Expand All @@ -398,6 +398,10 @@ void ValueVector::setValue(uint32_t pos, std::string val) {
StringVector::addString(this, pos, val.data(), val.length());
}

void ValueVector::setNull(uint32_t pos, bool isNull) {
nullMask->setNull(pos, isNull);
}

void StringVector::addString(ValueVector* vector, uint32_t vectorPos, ku_string_t& srcStr) {
assert(vector->dataType.getPhysicalType() == PhysicalTypeID::STRING);
auto stringBuffer = reinterpret_cast<StringAuxiliaryBuffer*>(vector->auxiliaryBuffer.get());
Expand Down
99 changes: 99 additions & 0 deletions src/function/vector_string_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,105 @@ using namespace kuzu::common;
namespace kuzu {
namespace function {

void BaseLowerUpperFunction::operation(common::ku_string_t& input, common::ku_string_t& result,
common::ValueVector& resultValueVector, bool isUpper) {
uint32_t resultLen = getResultLen((char*)input.getData(), input.len, isUpper);
result.len = resultLen;
if (resultLen <= common::ku_string_t::SHORT_STR_LENGTH) {
convertCase((char*)result.prefix, input.len, (char*)input.getData(), isUpper);
} else {
result.overflowPtr = reinterpret_cast<uint64_t>(
common::StringVector::getInMemOverflowBuffer(&resultValueVector)
->allocateSpace(result.len));
auto buffer = reinterpret_cast<char*>(result.overflowPtr);
convertCase(buffer, input.len, (char*)input.getData(), isUpper);
memcpy(result.prefix, buffer, common::ku_string_t::PREFIX_LENGTH);
}
}

void BaseStrOperation::operation(common::ku_string_t& input, common::ku_string_t& result,
common::ValueVector& resultValueVector, uint32_t (*strOperation)(char* data, uint32_t len)) {
if (input.len <= common::ku_string_t::SHORT_STR_LENGTH) {
memcpy(result.prefix, input.prefix, input.len);
result.len = strOperation((char*)result.prefix, input.len);
} else {
result.overflowPtr = reinterpret_cast<uint64_t>(
common::StringVector::getInMemOverflowBuffer(&resultValueVector)
->allocateSpace(input.len));
auto buffer = reinterpret_cast<char*>(result.overflowPtr);
memcpy(buffer, input.getData(), input.len);
result.len = strOperation(buffer, input.len);
memcpy(result.prefix, buffer,
result.len < common::ku_string_t::PREFIX_LENGTH ? result.len :
common::ku_string_t::PREFIX_LENGTH);
}
}

void Concat::concat(const char* left, uint32_t leftLen, const char* right, uint32_t rightLen,
common::ku_string_t& result, common::ValueVector& resultValueVector) {
auto len = leftLen + rightLen;
if (len <= common::ku_string_t::SHORT_STR_LENGTH /* concat's result is short */) {
memcpy(result.prefix, left, leftLen);
memcpy(result.prefix + leftLen, right, rightLen);
} else {
result.overflowPtr = reinterpret_cast<uint64_t>(
common::StringVector::getInMemOverflowBuffer(&resultValueVector)->allocateSpace(len));
auto buffer = reinterpret_cast<char*>(result.overflowPtr);
memcpy(buffer, left, leftLen);
memcpy(buffer + leftLen, right, rightLen);
memcpy(result.prefix, buffer, common::ku_string_t::PREFIX_LENGTH);
}
result.len = len;
}

void Repeat::operation(common::ku_string_t& left, int64_t& right, common::ku_string_t& result,
common::ValueVector& resultValueVector) {
result.len = left.len * right;
if (result.len <= common::ku_string_t::SHORT_STR_LENGTH) {
repeatStr((char*)result.prefix, left.getAsString(), right);
} else {
result.overflowPtr = reinterpret_cast<uint64_t>(
common::StringVector::getInMemOverflowBuffer(&resultValueVector)
->allocateSpace(result.len));
auto buffer = reinterpret_cast<char*>(result.overflowPtr);
repeatStr(buffer, left.getAsString(), right);
memcpy(result.prefix, buffer, common::ku_string_t::PREFIX_LENGTH);
}
}

void Reverse::operation(common::ku_string_t& input, common::ku_string_t& result,
common::ValueVector& resultValueVector) {
bool isAscii = true;
std::string inputStr = input.getAsString();
for (uint32_t i = 0; i < input.len; i++) {
if (inputStr[i] & 0x80) {
isAscii = false;
break;
}
}
if (isAscii) {
BaseStrOperation::operation(input, result, resultValueVector, reverseStr);
} else {
result.len = input.len;
if (result.len > common::ku_string_t::SHORT_STR_LENGTH) {
result.overflowPtr = reinterpret_cast<uint64_t>(
common::StringVector::getInMemOverflowBuffer(&resultValueVector)
->allocateSpace(input.len));
}
auto resultBuffer = result.len <= common::ku_string_t::SHORT_STR_LENGTH ?
reinterpret_cast<char*>(result.prefix) :
reinterpret_cast<char*>(result.overflowPtr);
utf8proc::utf8proc_grapheme_callback(
inputStr.c_str(), input.len, [&](size_t start, size_t end) {
memcpy(resultBuffer + input.len - end, input.getData() + start, end - start);
return true;
});
if (result.len > common::ku_string_t::SHORT_STR_LENGTH) {
memcpy(result.prefix, resultBuffer, common::ku_string_t::PREFIX_LENGTH);
}
}
}

vector_function_definitions ArrayExtractVectorFunction::getDefinitions() {
vector_function_definitions definitions;
definitions.emplace_back(make_unique<VectorFunctionDefinition>(ARRAY_EXTRACT_FUNC_NAME,
Expand Down
2 changes: 1 addition & 1 deletion src/include/common/data_chunk/sel_vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class SelectionVector {
}
inline sel_t* getSelectedPositionsBuffer() { return selectedPositionsBuffer.get(); }

static const sel_t INCREMENTAL_SELECTED_POS[DEFAULT_VECTOR_CAPACITY];
KUZU_API static const sel_t INCREMENTAL_SELECTED_POS[DEFAULT_VECTOR_CAPACITY];

public:
sel_t* selectedPositions;
Expand Down
9 changes: 2 additions & 7 deletions src/include/common/types/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,8 @@ class LogicalType {

public:
KUZU_API LogicalType() : typeID{LogicalTypeID::ANY}, extraTypeInfo{nullptr} {};
KUZU_API explicit LogicalType(LogicalTypeID typeID) : typeID{typeID}, extraTypeInfo{nullptr} {
setPhysicalType();
};
KUZU_API LogicalType(LogicalTypeID typeID, std::unique_ptr<ExtraTypeInfo> extraTypeInfo)
: typeID{typeID}, extraTypeInfo{std::move(extraTypeInfo)} {
setPhysicalType();
};
explicit KUZU_API LogicalType(LogicalTypeID typeID);
KUZU_API LogicalType(LogicalTypeID typeID, std::unique_ptr<ExtraTypeInfo> extraTypeInfo);
// For deserialize only.
LogicalType(LogicalTypeID typeID, PhysicalTypeID physicalType,
std::unique_ptr<ExtraTypeInfo> extraTypeInfo)
Expand Down
8 changes: 4 additions & 4 deletions src/include/common/vector/value_vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ValueVector {
assert(dataTypeID != LogicalTypeID::VAR_LIST);
}

~ValueVector() = default;
KUZU_API ~ValueVector() = default;

void setState(std::shared_ptr<DataChunkState> state_);

Expand All @@ -41,7 +41,7 @@ class ValueVector {
nullMask->setNullFromRange(startPos, len, false);
}
inline const uint64_t* getNullMaskData() { return nullMask->getData(); }
inline void setNull(uint32_t pos, bool isNull) { nullMask->setNull(pos, isNull); }
KUZU_API void setNull(uint32_t pos, bool isNull);
inline uint8_t isNull(uint32_t pos) const { return nullMask->isNull(pos); }
inline void setAsSingleNullEntry() {
state->selVector->selectedSize = 1;
Expand All @@ -59,7 +59,7 @@ class ValueVector {
return ((T*)valueBuffer.get())[pos];
}
template<typename T>
void setValue(uint32_t pos, T val);
KUZU_API void setValue(uint32_t pos, T val);
// copyFromRowData assumes rowData is non-NULL.
void copyFromRowData(uint32_t pos, const uint8_t* rowData);
// copyToRowData assumes srcVectorData is non-NULL.
Expand All @@ -83,7 +83,7 @@ class ValueVector {
inline void setSequential() { _isSequential = true; }
inline bool isSequential() const { return _isSequential; }

void resetAuxiliaryBuffer();
KUZU_API void resetAuxiliaryBuffer();

// If there is still non-null values after discarding, return true. Otherwise, return false.
// For an unflat vector, its selection vector is also updated to the resultSelVector.
Expand Down
18 changes: 3 additions & 15 deletions src/include/function/string/functions/base_lower_upper_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <cassert>
#include <cstring>

#include "common/api.h"
#include "common/types/ku_string.h"
#include "common/vector/value_vector.h"
#include "utf8proc.h"
Expand All @@ -12,21 +13,8 @@ namespace function {

struct BaseLowerUpperFunction {

static inline void operation(common::ku_string_t& input, common::ku_string_t& result,
common::ValueVector& resultValueVector, bool isUpper) {
uint32_t resultLen = getResultLen((char*)input.getData(), input.len, isUpper);
result.len = resultLen;
if (resultLen <= common::ku_string_t::SHORT_STR_LENGTH) {
convertCase((char*)result.prefix, input.len, (char*)input.getData(), isUpper);
} else {
result.overflowPtr = reinterpret_cast<uint64_t>(
common::StringVector::getInMemOverflowBuffer(&resultValueVector)
->allocateSpace(result.len));
auto buffer = reinterpret_cast<char*>(result.overflowPtr);
convertCase(buffer, input.len, (char*)input.getData(), isUpper);
memcpy(result.prefix, buffer, common::ku_string_t::PREFIX_LENGTH);
}
}
KUZU_API static void operation(common::ku_string_t& input, common::ku_string_t& result,
common::ValueVector& resultValueVector, bool isUpper);

private:
static uint32_t getResultLen(char* inputStr, uint32_t inputLen, bool isUpper);
Expand Down
22 changes: 3 additions & 19 deletions src/include/function/string/functions/base_str_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,16 @@
#include <cassert>
#include <cstring>

#include "common/api.h"
#include "common/types/ku_string.h"

namespace kuzu {
namespace function {

struct BaseStrOperation {
public:
static inline void operation(common::ku_string_t& input, common::ku_string_t& result,
common::ValueVector& resultValueVector,
uint32_t (*strOperation)(char* data, uint32_t len)) {
if (input.len <= common::ku_string_t::SHORT_STR_LENGTH) {
memcpy(result.prefix, input.prefix, input.len);
result.len = strOperation((char*)result.prefix, input.len);
} else {
result.overflowPtr = reinterpret_cast<uint64_t>(
common::StringVector::getInMemOverflowBuffer(&resultValueVector)
->allocateSpace(input.len));
auto buffer = reinterpret_cast<char*>(result.overflowPtr);
memcpy(buffer, input.getData(), input.len);
result.len = strOperation(buffer, input.len);
memcpy(result.prefix, buffer,
result.len < common::ku_string_t::PREFIX_LENGTH ?
result.len :
common::ku_string_t::PREFIX_LENGTH);
}
}
KUZU_API static void operation(common::ku_string_t& input, common::ku_string_t& result,
common::ValueVector& resultValueVector, uint32_t (*strOperation)(char* data, uint32_t len));
};

} // namespace function
Expand Down
20 changes: 3 additions & 17 deletions src/include/function/string/functions/concat_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <cassert>
#include <cstring>

#include "common/api.h"
#include "common/types/ku_string.h"
#include "common/vector/value_vector.h"

Expand All @@ -15,23 +16,8 @@ struct Concat {
assert(false);
}

static void concat(const char* left, uint32_t leftLen, const char* right, uint32_t rightLen,
common::ku_string_t& result, common::ValueVector& resultValueVector) {
auto len = leftLen + rightLen;
if (len <= common::ku_string_t::SHORT_STR_LENGTH /* concat's result is short */) {
memcpy(result.prefix, left, leftLen);
memcpy(result.prefix + leftLen, right, rightLen);
} else {
result.overflowPtr = reinterpret_cast<uint64_t>(
common::StringVector::getInMemOverflowBuffer(&resultValueVector)
->allocateSpace(len));
auto buffer = reinterpret_cast<char*>(result.overflowPtr);
memcpy(buffer, left, leftLen);
memcpy(buffer + leftLen, right, rightLen);
memcpy(result.prefix, buffer, common::ku_string_t::PREFIX_LENGTH);
}
result.len = len;
}
KUZU_API static void concat(const char* left, uint32_t leftLen, const char* right,
uint32_t rightLen, common::ku_string_t& result, common::ValueVector& resultValueVector);
};

template<>
Expand Down
Loading

0 comments on commit 10233ad

Please sign in to comment.