mirror of
https://github.com/hanzo-ds/cpp.git
synced 2026-10-30 20:31:26 +00:00
Pure rename applied on top of upstream tag v2.6.2 (8d2415d6), not HEAD.
The fork was cut at 737145d = v2.6.2-57, which still declared version 2.6.2
in version.h; renaming there would have shipped 57 unreleased commits wearing
a 2.6.2 label. Reset to the tag first so this commit changes names only.
clickhouse/ -> datastore/ (public include root)
namespace clickhouse -> namespace datastore
CLICKHOUSE_CPP_VERSION -> DATASTORE_CPP_VERSION
clickhouse-cpp-lib/-ut -> datastore-cpp-lib/-ut (CMake, Bazel)
CH_MAP_BOOL_TO_UINT8 -> DS_MAP_BOOL_TO_UINT8
CLICKHOUSE_* -> DATASTORE_* (test env vars)
doc links -> docs.hanzo.ai/datastore
This client speaks the NATIVE binary protocol only - there is no HTTP path
and no X-ClickHouse-* header anywhere in it, so the header rename that the
HTTP clients required does not apply and nothing here was broken.
The one string that reaches the wire is CLIENT_NAME, sent by both SendHello
and SendQuery's ClientInfo from a single macro, and it lands in
system.query_log.client_name. Both sites still read the one macro, so they
stay consistent and the server's Hello/Query consistency check is satisfied.
Old rows keep the old name; that is a reporting discontinuity, not a
migration, since nothing keys on it.
CI is repointed at our own server: ghcr.io/hanzoai/datastore:26.2.3.2, the
image production runs. Its entrypoint honours DATASTORE_SKIP_USER_SETUP, not
the CLICKHOUSE_ spelling the compose file used, and its config lives in
/etc/hanzo-datastore-server. ci/docker-compose/config.xml is now layered in
as a config.d drop-in so the image keeps its own white-labelling. That file
and users.xml deliberately keep a <clickhouse> root: it must match the roots
of the drop-ins the image ships, and a mismatch fails silently - the server
logs "Merging bypassed" and starts with every drop-in discarded.
The remote-TLS suites used to default to the third-party host
play.clickhouse.com. They now read DATASTORE_SECURE*_HOST and skip when it is
unset rather than point at a host we do not run.
Dropped as upstream infrastructure with no meaning here: AI_POLICY.md
(upstream's policy about their codebase), .travis.yml (dead CI referencing a
third-party apt repo), cross-repo-bug-relay.yml (relays our issues into an
upstream triage repo). LICENSE keeps its copyright notice, as Apache-2.0
requires.
Verified: cmake configure + 115-target build clean; the full suite is green
against ghcr.io/hanzoai/datastore:26.2.3.2 (894 passed, 0 failed); the
pristine v2.6.2 build run against that same server passes the identical set,
and both logged the same 3914 queries under their respective client names.
483 lines
16 KiB
C++
483 lines
16 KiB
C++
#include <datastore/columns/array.h>
|
|
#include <datastore/columns/tuple.h>
|
|
#include <datastore/columns/date.h>
|
|
#include <datastore/columns/enum.h>
|
|
#include <datastore/columns/factory.h>
|
|
#include <datastore/columns/lowcardinality.h>
|
|
#include <datastore/columns/nullable.h>
|
|
#include <datastore/columns/numeric.h>
|
|
#include <datastore/columns/string.h>
|
|
#include <datastore/columns/uuid.h>
|
|
#include <datastore/columns/ip4.h>
|
|
#include <datastore/columns/ip6.h>
|
|
#include <datastore/base/input.h>
|
|
#include <datastore/base/output.h>
|
|
|
|
#include <gtest/gtest.h>
|
|
#include "utils.h"
|
|
|
|
#include <string_view>
|
|
#include <sstream>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
using namespace datastore;
|
|
|
|
template <typename NestedColumnType, typename ValuesContainer>
|
|
std::shared_ptr<ColumnArray> Create2DArray(const ValuesContainer& values) {
|
|
auto result = std::make_shared<ColumnArray>(std::make_shared<ColumnArray>(std::make_shared<NestedColumnType>()));
|
|
for (size_t i = 0; i < values.size(); ++i) {
|
|
auto array_col = std::make_shared<ColumnArray>(std::make_shared<NestedColumnType>());
|
|
for (size_t j = 0; j < values[i].size(); ++j)
|
|
array_col->AppendAsColumn(std::make_shared<ColumnUInt64>(values[i][j]));
|
|
|
|
result->AppendAsColumn(array_col);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template <typename NestedColumnType, typename ValuesContainer>
|
|
std::shared_ptr<ColumnArray> CreateArray(const ValuesContainer& values) {
|
|
auto result = std::make_shared<ColumnArray>(std::make_shared<NestedColumnType>());
|
|
for (size_t i = 0; i < values.size(); ++i) {
|
|
result->AppendAsColumn(std::make_shared<NestedColumnType>(values[i]));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
}
|
|
|
|
TEST(ColumnArray, Append) {
|
|
auto arr1 = std::make_shared<ColumnArray>(std::make_shared<ColumnUInt64>());
|
|
auto arr2 = std::make_shared<ColumnArray>(std::make_shared<ColumnUInt64>());
|
|
|
|
auto id = std::make_shared<ColumnUInt64>();
|
|
id->Append(1);
|
|
arr1->AppendAsColumn(id);
|
|
|
|
id->Append(3);
|
|
arr2->AppendAsColumn(id);
|
|
|
|
arr1->Append(arr2);
|
|
|
|
auto col = arr1->GetAsColumn(1);
|
|
|
|
ASSERT_EQ(arr1->Size(), 2u);
|
|
ASSERT_EQ(col->As<ColumnUInt64>()->At(0), 1u);
|
|
ASSERT_EQ(col->As<ColumnUInt64>()->At(1), 3u);
|
|
}
|
|
|
|
TEST(ColumnArray, ArrayOfDecimal) {
|
|
auto column = std::make_shared<datastore::ColumnDecimal>(18, 10);
|
|
auto array = std::make_shared<datastore::ColumnArray>(column->CloneEmpty());
|
|
|
|
column->Append("1");
|
|
column->Append("2");
|
|
EXPECT_EQ(2u, column->Size());
|
|
|
|
array->AppendAsColumn(column);
|
|
ASSERT_EQ(1u, array->Size());
|
|
EXPECT_EQ(2u, array->GetAsColumn(0)->Size());
|
|
}
|
|
|
|
TEST(ColumnArray, GetAsColumn) {
|
|
// Verify that result of GetAsColumn
|
|
// - is of proper type
|
|
// - has expected length
|
|
// - values match ones predefined ones
|
|
|
|
const std::vector<std::vector<uint64_t>> values = {
|
|
{1u, 2u, 3u},
|
|
{4u, 5u, 6u, 7u, 8u, 9u},
|
|
{0u},
|
|
{},
|
|
{13, 14}
|
|
};
|
|
|
|
auto array = CreateArray<ColumnUInt64>(values);
|
|
ASSERT_EQ(values.size(), array->Size());
|
|
|
|
for (size_t i = 0; i < values.size(); ++i) {
|
|
auto row = array->GetAsColumn(i);
|
|
std::shared_ptr<ColumnUInt64> typed_row;
|
|
|
|
EXPECT_NO_THROW(typed_row = row->As<ColumnUInt64>());
|
|
EXPECT_TRUE(CompareRecursive(values[i], *typed_row));
|
|
}
|
|
|
|
EXPECT_THROW(array->GetAsColumn(array->Size()), ValidationError);
|
|
EXPECT_THROW(array->GetAsColumn(array->Size() + 1), ValidationError);
|
|
}
|
|
|
|
TEST(ColumnArray, Slice) {
|
|
const std::vector<std::vector<uint64_t>> values = {
|
|
{1u, 2u, 3u},
|
|
{4u, 5u, 6u, 7u, 8u, 9u},
|
|
{0u},
|
|
{},
|
|
{13, 14, 15}
|
|
};
|
|
|
|
std::shared_ptr<ColumnArray> untyped_array = CreateArray<ColumnUInt64>(values);
|
|
|
|
for (size_t i = 0; i < values.size() - 1; ++i) {
|
|
auto slice = untyped_array->Slice(i, 1)->AsStrict<ColumnArray>();
|
|
EXPECT_EQ(1u, slice->Size());
|
|
EXPECT_TRUE(CompareRecursive(values[i], *slice->GetAsColumnTyped<ColumnUInt64>(0)));
|
|
}
|
|
|
|
EXPECT_EQ(0u, untyped_array->Slice(0, 0)->Size());
|
|
EXPECT_ANY_THROW(untyped_array->Slice(values.size(), 1));
|
|
EXPECT_ANY_THROW(untyped_array->Slice(0, values.size() + 1));
|
|
}
|
|
|
|
TEST(ColumnArray, Slice_2D) {
|
|
// Verify that ColumnArray::Slice on 2D Array produces a 2D Array of proper type, size and contents.
|
|
// Also check that slices can be of any size.
|
|
const std::vector<std::vector<std::vector<uint64_t>>> values = {
|
|
{{1u, 2u}, {3u}},
|
|
{{4u}, {5u, 6u, 7u}, {8u, 9u}, {}},
|
|
{{0u}},
|
|
{{}},
|
|
{{13}, {14, 15}}
|
|
};
|
|
|
|
std::shared_ptr<ColumnArray> untyped_array = Create2DArray<ColumnUInt64>(values);
|
|
for (size_t i = 0; i < values.size() - 1; ++i) {
|
|
for (size_t slice_size = 0; slice_size < values.size() - i; ++slice_size) {
|
|
auto slice = untyped_array->Slice(i, slice_size)->AsStrict<ColumnArray>();
|
|
EXPECT_EQ(slice_size, slice->Size());
|
|
|
|
for (size_t slice_row = 0; slice_row < slice_size; ++slice_row) {
|
|
SCOPED_TRACE(::testing::Message() << "i: " << i << " slice_size:" << slice_size << " row:" << slice_row);
|
|
auto val = slice->GetAsColumnTyped<ColumnArray>(slice_row);
|
|
ASSERT_EQ(values[i + slice_row].size(), val->Size());
|
|
|
|
for (size_t j = 0; j < values[i + slice_row].size(); ++j) {
|
|
ASSERT_TRUE(CompareRecursive(values[i + slice_row][j], *val->GetAsColumnTyped<ColumnUInt64>(j)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
template <typename ArrayTSpecialization, typename RowValuesContainer>
|
|
auto AppendRowAndTest(ArrayTSpecialization& array, const RowValuesContainer& values) {
|
|
const size_t prev_size = array.Size();
|
|
|
|
array.Append(values);
|
|
EXPECT_EQ(prev_size + 1u, array.Size());
|
|
|
|
EXPECT_TRUE(CompareRecursive(values, array.At(prev_size)));
|
|
EXPECT_TRUE(CompareRecursive(values, array[prev_size]));
|
|
|
|
// Check that both subscript and At() work properly.
|
|
const auto & new_row = array.At(prev_size);
|
|
for (size_t i = 0; i < values.size(); ++i) {
|
|
EXPECT_TRUE(CompareRecursive(*(values.begin() + i), new_row[i]))
|
|
<< " at pos: " << i;
|
|
EXPECT_TRUE(CompareRecursive(*(values.begin() + i), new_row.At(i)))
|
|
<< " at pos: " << i;
|
|
}
|
|
EXPECT_THROW(new_row.At(new_row.size() + 1), datastore::ValidationError);
|
|
};
|
|
|
|
template <typename NestedColumnType, typename AllValuesContainer>
|
|
auto CreateAndTestColumnArrayT(const AllValuesContainer& all_values) {
|
|
auto array = std::make_shared<datastore::ColumnArrayT<NestedColumnType>>();
|
|
|
|
for (const auto & row : all_values) {
|
|
EXPECT_NO_FATAL_FAILURE(AppendRowAndTest(*array, row));
|
|
}
|
|
EXPECT_TRUE(CompareRecursive(all_values, *array));
|
|
EXPECT_THROW(array->At(array->Size() + 1), datastore::ValidationError);
|
|
|
|
return array;
|
|
}
|
|
|
|
TEST(ColumnArrayT, SimpleUInt64) {
|
|
auto array = std::make_shared<datastore::ColumnArrayT<ColumnUInt64>>();
|
|
array->Append({0, 1, 2});
|
|
|
|
ASSERT_EQ(1u, array->Size());
|
|
EXPECT_EQ(0u, array->At(0).At(0));
|
|
EXPECT_EQ(1u, (*array)[0][1]);
|
|
|
|
EXPECT_THROW(array->At(2), ValidationError);
|
|
EXPECT_THROW(array->At(0).At(3), ValidationError);
|
|
EXPECT_THROW((*array)[0].At(3), ValidationError);
|
|
}
|
|
|
|
TEST(ColumnArrayT, SimpleFixedString) {
|
|
using namespace std::literals;
|
|
auto array = std::make_shared<ColumnArrayT<ColumnFixedString>>(6);
|
|
array->Append({"hello", "world"});
|
|
|
|
// Additional \0 since strings are padded from right with zeros in FixedString(6).
|
|
EXPECT_EQ("hello\0"sv, array->At(0).At(0));
|
|
|
|
auto row = array->At(0);
|
|
EXPECT_EQ("hello\0"sv, row.At(0));
|
|
EXPECT_EQ(6u, row[0].length());
|
|
EXPECT_EQ("hello", row[0].substr(0, 5));
|
|
|
|
EXPECT_EQ("world\0"sv, (*array)[0][1]);
|
|
}
|
|
|
|
TEST(ColumnArrayT, JSON) {
|
|
using namespace std::literals;
|
|
auto i1 = R"({"item": 1})"sv;
|
|
auto i2 = R"({"item": 2})"sv;
|
|
auto i3 = R"({"item": 3})"sv;
|
|
auto array = std::make_shared<ColumnArrayT<ColumnJSON>>();
|
|
array->Append({i1});
|
|
array->Append({i2, i3});
|
|
|
|
EXPECT_EQ(i1, array->At(0).At(0));
|
|
EXPECT_EQ(i2, array->At(1).At(0));
|
|
EXPECT_EQ(i3, array->At(1).At(1));
|
|
|
|
auto r1 = array->At(0);
|
|
EXPECT_EQ(1u, r1.Size());
|
|
EXPECT_EQ(i1, r1.At(0));
|
|
|
|
auto r2 = array->At(1);
|
|
EXPECT_EQ(2u, r2.Size());
|
|
EXPECT_EQ(i2, r2.At(0));
|
|
EXPECT_EQ(i3, r2.At(1));
|
|
}
|
|
|
|
TEST(ColumnArrayT, SimpleUInt64_2D) {
|
|
// Nested 2D-arrays are supported too:
|
|
auto array = std::make_shared<ColumnArrayT<ColumnArrayT<ColumnUInt64>>>();
|
|
array->Append(std::vector<std::vector<unsigned int>>{{0}, {1, 1}, {2, 2, 2}});
|
|
|
|
ASSERT_EQ(1u, array->Size());
|
|
EXPECT_EQ(0u, array->At(0).At(0).At(0));
|
|
EXPECT_EQ(1u, (*array)[0][1][1]);
|
|
|
|
EXPECT_THROW(array->At(2), ValidationError);
|
|
}
|
|
|
|
TEST(ColumnArrayT, UInt64) {
|
|
// Check inserting\reading back data from datastore::ColumnArrayT<ColumnUInt64>
|
|
|
|
const std::vector<std::vector<unsigned int>> values = {
|
|
{1u, 2u, 3u},
|
|
{4u, 5u, 6u, 7u, 8u, 9u},
|
|
{0u},
|
|
{},
|
|
{13, 14}
|
|
};
|
|
CreateAndTestColumnArrayT<ColumnUInt64>(values);
|
|
}
|
|
|
|
TEST(ColumnArrayT, UInt64_2D) {
|
|
// Check inserting\reading back data from 2D array: ColumnArrayT<ColumnArrayT<ColumnUInt64>>
|
|
|
|
const std::vector<std::vector<std::vector<unsigned int>>> values = {
|
|
{{1u, 2u, 3u}, {4u, 5u, 6u}},
|
|
{{4u, 5u, 6u}, {7u, 8u, 9u}, {10u, 11u}},
|
|
{{}, {}},
|
|
{},
|
|
{{13, 14}, {}}
|
|
};
|
|
|
|
auto array_ptr = CreateAndTestColumnArrayT<ColumnArrayT<ColumnUInt64>>(values);
|
|
const auto & array = *array_ptr;
|
|
|
|
{
|
|
EXPECT_EQ(0u, array[3].size());
|
|
|
|
// operator[] doesn't check bounds.
|
|
// On empty rows attempt to access out-of-bound elements
|
|
// would actually cause access to the elements of the next row.
|
|
// hence non-0 value of `array[3][0].size()`,
|
|
// it is effectively the same as `array[3 + 1][0].size()`
|
|
EXPECT_EQ(2u, array[3][0].size());
|
|
EXPECT_EQ(14u, array[3][0][1]);
|
|
EXPECT_EQ(0u, array[3][1].size());
|
|
}
|
|
}
|
|
|
|
TEST(ColumnArrayT, Wrap_UInt64) {
|
|
// Check that ColumnArrayT can wrap a pre-existing ColumnArray.
|
|
|
|
const std::vector<std::vector<uint64_t>> values = {
|
|
{1u, 2u, 3u},
|
|
{4u, 5u, 6u, 7u, 8u, 9u},
|
|
{0u},
|
|
{},
|
|
{13, 14}
|
|
};
|
|
|
|
auto wrapped_array = ColumnArrayT<ColumnUInt64>::Wrap(CreateArray<ColumnUInt64>(values));
|
|
const auto & array = *wrapped_array;
|
|
|
|
EXPECT_TRUE(CompareRecursive(values, array));
|
|
}
|
|
|
|
TEST(ColumnArrayT, Wrap_UInt64_2D) {
|
|
// Check that ColumnArrayT can wrap a pre-existing ColumnArray.
|
|
|
|
const std::vector<std::vector<std::vector<uint64_t>>> values = {
|
|
{{1u, 2u}, {3u}},
|
|
{{4u}, {5u, 6u, 7u}, {8u, 9u}, {}},
|
|
{{0u}},
|
|
{{}},
|
|
{{13}, {14, 15}}
|
|
};
|
|
|
|
auto wrapped_array = ColumnArrayT<ColumnArrayT<ColumnUInt64>>::Wrap(Create2DArray<ColumnUInt64>(values));
|
|
const auto & array = *wrapped_array;
|
|
|
|
EXPECT_TRUE(CompareRecursive(values, array));
|
|
}
|
|
|
|
TEST(ColumnArrayT, Bool) {
|
|
// Check inserting\reading back data from datastore::ColumnArrayT<ColumnBool>
|
|
|
|
const std::vector<std::vector<uint8_t>> values = {
|
|
{1u, 0u, 0u},
|
|
{0u, 1u, 1u, 0u, 1u, 0u},
|
|
{0u},
|
|
{},
|
|
{1u, 0u}
|
|
};
|
|
CreateAndTestColumnArrayT<ColumnBool>(values);
|
|
}
|
|
|
|
TEST(ColumnArrayT, left_value_no_move) {
|
|
std::string value0 = "000000000000000000";
|
|
std::string value1 = "111111111111111111";
|
|
std::string value2 = "222222222222222222";
|
|
std::vector<std::vector<std::string>> all_values{
|
|
{ value0, value1, value2},
|
|
{ value0, value1, value2},
|
|
{ value0, value1, value2}
|
|
};
|
|
size_t origin_size = 3;
|
|
auto array = std::make_shared<datastore::ColumnArrayT<datastore::ColumnArrayT<ColumnString>>>();
|
|
array->Append(all_values);
|
|
EXPECT_EQ(3u, (*array)[0][0].size());
|
|
EXPECT_EQ(3u, (*array)[0][1].size());
|
|
EXPECT_EQ(3u, (*array)[0][2].size());
|
|
|
|
EXPECT_EQ(value0, (*array)[0][0][0]);
|
|
EXPECT_EQ(value1, (*array)[0][1][1]);
|
|
EXPECT_EQ(value2, (*array)[0][2][2]);
|
|
|
|
for (const auto& values : all_values) {
|
|
EXPECT_EQ(origin_size, values.size());
|
|
}
|
|
|
|
EXPECT_EQ(origin_size, all_values.size());
|
|
for (const auto& values : all_values) {
|
|
EXPECT_EQ(values[0], value0);
|
|
EXPECT_EQ(values[1], value1);
|
|
EXPECT_EQ(values[2], value2);
|
|
}
|
|
}
|
|
|
|
TEST(ColumnArrayT, right_value_move) {
|
|
std::string value0 = "000000000000000000";
|
|
std::string value1 = "111111111111111111";
|
|
std::string value2 = "222222222222222222";
|
|
std::vector<std::vector<std::string>> all_values{
|
|
{ value0, value1, value2},
|
|
{ value0, value1, value2},
|
|
{ value0, value1, value2}
|
|
};
|
|
auto array = std::make_shared<datastore::ColumnArrayT<datastore::ColumnArrayT<ColumnString>>>();
|
|
array->Append(std::move(all_values));
|
|
EXPECT_EQ(3u, (*array)[0][0].size());
|
|
EXPECT_EQ(3u, (*array)[0][1].size());
|
|
EXPECT_EQ(3u, (*array)[0][2].size());
|
|
|
|
EXPECT_EQ(value0, (*array)[0][0][0]);
|
|
EXPECT_EQ(value1, (*array)[0][1][1]);
|
|
EXPECT_EQ(value2, (*array)[0][2][2]);
|
|
|
|
// Here we don't care about the size of the container from which all values were moved-out.
|
|
//EXPECT_EQ(0u, all_values.size());
|
|
}
|
|
|
|
TEST(ColumnArrayT, const_right_value_no_move) {
|
|
std::string value0 = "000000000000000000";
|
|
std::string value1 = "111111111111111111";
|
|
std::string value2 = "222222222222222222";
|
|
const std::vector<std::vector<std::string>> all_values{
|
|
{ value0, value1, value2},
|
|
{ value0, value1, value2},
|
|
{ value0, value1, value2}
|
|
};
|
|
size_t origin_size = 3;
|
|
auto array = std::make_shared<datastore::ColumnArrayT<datastore::ColumnArrayT<ColumnString>>>();
|
|
array->Append(std::move(all_values));
|
|
EXPECT_EQ(3u, (*array)[0][0].size());
|
|
EXPECT_EQ(3u, (*array)[0][1].size());
|
|
EXPECT_EQ(3u, (*array)[0][2].size());
|
|
|
|
EXPECT_EQ(value0, (*array)[0][0][0]);
|
|
EXPECT_EQ(value1, (*array)[0][1][1]);
|
|
EXPECT_EQ(value2, (*array)[0][2][2]);
|
|
|
|
for (const auto& values : all_values) {
|
|
EXPECT_EQ(origin_size, values.size());
|
|
}
|
|
|
|
EXPECT_EQ(origin_size, all_values.size());
|
|
for (const auto& values : all_values) {
|
|
EXPECT_EQ(values[0], value0);
|
|
EXPECT_EQ(values[1], value1);
|
|
EXPECT_EQ(values[2], value2);
|
|
}
|
|
}
|
|
|
|
TEST(ColumnArray, GetData) {
|
|
auto col = std::make_shared<ColumnArray>(std::make_shared<ColumnUInt64>());
|
|
col->AppendAsColumn(std::make_shared<ColumnUInt64>(std::vector<uint64_t>{1, 2, 3}));
|
|
col->AppendAsColumn(std::make_shared<ColumnUInt64>(std::vector<uint64_t>{4, 5}));
|
|
|
|
ColumnRef data = col->GetData();
|
|
EXPECT_EQ(data->Size(), 5u);
|
|
|
|
const auto& ccol = *col;
|
|
std::shared_ptr<const Column> cdata = ccol.GetData();
|
|
EXPECT_EQ(cdata->Size(), 5u);
|
|
}
|
|
|
|
TEST(ColumnArray, GetOffsets) {
|
|
auto col = std::make_shared<ColumnArray>(std::make_shared<ColumnUInt64>());
|
|
col->AppendAsColumn(std::make_shared<ColumnUInt64>(std::vector<uint64_t>{1, 2, 3}));
|
|
col->AppendAsColumn(std::make_shared<ColumnUInt64>(std::vector<uint64_t>{4, 5}));
|
|
|
|
auto& offsets = col->GetOffsets();
|
|
ASSERT_EQ(offsets->Size(), 2u);
|
|
EXPECT_EQ((*offsets)[0], 3u);
|
|
EXPECT_EQ((*offsets)[1], 5u);
|
|
|
|
const auto& ccol = *col;
|
|
std::shared_ptr<const ColumnUInt64> coffsets = ccol.GetOffsets();
|
|
EXPECT_EQ((*coffsets)[0], 3u);
|
|
EXPECT_EQ((*coffsets)[1], 5u);
|
|
}
|
|
|
|
TEST(ColumnArray, GetOffsetAndSize) {
|
|
auto col = std::make_shared<ColumnArray>(std::make_shared<ColumnUInt64>());
|
|
col->AppendAsColumn(std::make_shared<ColumnUInt64>(std::vector<uint64_t>{10, 20}));
|
|
col->AppendAsColumn(std::make_shared<ColumnUInt64>(std::vector<uint64_t>{30}));
|
|
col->AppendAsColumn(std::make_shared<ColumnUInt64>(std::vector<uint64_t>{}));
|
|
|
|
EXPECT_EQ(col->GetOffset(0), 0u);
|
|
EXPECT_EQ(col->GetOffset(1), 2u);
|
|
EXPECT_EQ(col->GetOffset(2), 3u);
|
|
|
|
EXPECT_EQ(col->GetSize(0), 2u);
|
|
EXPECT_EQ(col->GetSize(1), 1u);
|
|
EXPECT_EQ(col->GetSize(2), 0u);
|
|
}
|