Skip to content

Commit ccac8bb

Browse files
committed
test: align protocol 3.1 partition key fixture
1 parent ad9e6bb commit ccac8bb

1 file changed

Lines changed: 79 additions & 1 deletion

File tree

‎example-worker/table/splits.cpp‎

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323

2424
#include <arrow/array.h>
2525
#include <arrow/array/builder_binary.h>
26+
#include <arrow/array/builder_nested.h>
2627
#include <arrow/array/builder_primitive.h>
28+
#include <arrow/io/memory.h>
29+
#include <arrow/ipc/writer.h>
2730
#include <arrow/record_batch.h>
2831
#include <arrow/type.h>
2932

@@ -76,6 +79,75 @@ std::optional<std::tuple<int64_t, int64_t, int64_t>> decode_indexed_range(
7679
return std::tuple{ordinal_begin->first, ordinal_begin->second, end_unused->second};
7780
}
7881

82+
std::string encode_batch(const std::shared_ptr<arrow::RecordBatch>& batch) {
83+
auto sink = arrow::io::BufferOutputStream::Create().ValueOrDie();
84+
auto writer = arrow::ipc::MakeStreamWriter(sink, batch->schema()).ValueOrDie();
85+
(void)writer->WriteRecordBatch(*batch);
86+
(void)writer->Close();
87+
return sink->Finish().ValueOrDie()->ToString();
88+
}
89+
90+
std::shared_ptr<arrow::Array> one_string_list(const std::vector<std::string>& values) {
91+
arrow::ListBuilder builder(arrow::default_memory_pool(),
92+
std::make_unique<arrow::StringBuilder>());
93+
(void)builder.Append();
94+
auto& items = static_cast<arrow::StringBuilder&>(*builder.value_builder());
95+
for (const auto& value : values) (void)items.Append(value);
96+
return builder.Finish().ValueOrDie();
97+
}
98+
99+
std::shared_ptr<arrow::Array> one_binary_list(const std::vector<std::string>& values) {
100+
arrow::ListBuilder builder(arrow::default_memory_pool(),
101+
std::make_unique<arrow::BinaryBuilder>());
102+
(void)builder.Append();
103+
auto& items = static_cast<arrow::BinaryBuilder&>(*builder.value_builder());
104+
for (const auto& value : values) (void)items.Append(value);
105+
return builder.Finish().ValueOrDie();
106+
}
107+
108+
std::string identity_key_grouping(const std::string& column) {
109+
const auto path = encode_batch(arrow::RecordBatch::Make(
110+
arrow::schema({arrow::field("components", arrow::list(arrow::utf8()), false)}), 1,
111+
{one_string_list({column})}));
112+
113+
arrow::StringBuilder id_builder;
114+
(void)id_builder.Append("vgi.identity/1");
115+
arrow::BinaryBuilder parameters_builder;
116+
(void)parameters_builder.AppendNull();
117+
const auto transform = encode_batch(arrow::RecordBatch::Make(
118+
arrow::schema({arrow::field("id", arrow::utf8(), false),
119+
arrow::field("inputs", arrow::list(arrow::binary()), false),
120+
arrow::field("parameters", arrow::binary(), true)}),
121+
1,
122+
{id_builder.Finish().ValueOrDie(), one_binary_list({path}),
123+
parameters_builder.Finish().ValueOrDie()}));
124+
125+
return encode_batch(arrow::RecordBatch::Make(
126+
arrow::schema({arrow::field("keys", arrow::list(arrow::binary()), false)}), 1,
127+
{one_binary_list({transform})}));
128+
}
129+
130+
std::optional<std::string> partition_key_value(const std::string& country,
131+
const std::string& mode) {
132+
if (mode == "missing") return std::nullopt;
133+
if (mode == "wrong_type") {
134+
arrow::Int64Builder values;
135+
(void)values.Append(1);
136+
return encode_batch(
137+
arrow::RecordBatch::Make(arrow::schema({arrow::field("country", arrow::int64(), true)}),
138+
1, {values.Finish().ValueOrDie()}));
139+
}
140+
if (mode != "valid" && mode != "two_rows") {
141+
throw std::invalid_argument("unknown split_partitioned key_mode: " + mode);
142+
}
143+
arrow::StringBuilder values;
144+
(void)values.Append(country);
145+
if (mode == "two_rows") (void)values.Append(country);
146+
auto array = values.Finish().ValueOrDie();
147+
return encode_batch(arrow::RecordBatch::Make(
148+
arrow::schema({arrow::field("country", arrow::utf8(), true)}), array->length(), {array}));
149+
}
150+
79151
std::shared_ptr<arrow::Schema> n_schema() {
80152
return arrow::schema({arrow::field("n", arrow::int64(), /*nullable=*/false)});
81153
}
@@ -481,7 +553,10 @@ class SplitPartitioned : public vgi::TableFunction {
481553
}
482554

483555
std::vector<vgi::ArgSpec> argument_specs() const override {
484-
return {vgi::ArgSpec::named("rows_per_country", "int64", "Rows per country")};
556+
return {vgi::ArgSpec::named("rows_per_country", "int64", "Rows per country"),
557+
vgi::ArgSpec::named(
558+
"key_mode", "varchar",
559+
"Test-only Protocol 3.1 key shape: valid, missing, two_rows, or wrong_type")};
485560
}
486561

487562
std::shared_ptr<arrow::Schema> bind(const vgi::BindParams&) const override {
@@ -494,14 +569,17 @@ class SplitPartitioned : public vgi::TableFunction {
494569
vgi::PlanResult plan(const vgi::BindParams& params, const vgi::PlanParams&) const override {
495570
const int64_t rows =
496571
std::max<int64_t>(0, params.arguments.named_int64("rows_per_country").value_or(0));
572+
const auto key_mode = params.arguments.named_string("key_mode").value_or("valid");
497573
vgi::PlanResult result;
498574
result.estimated_total_splits = static_cast<int64_t>(kCountries.size());
499575
result.estimated_total_rows = rows * static_cast<int64_t>(kCountries.size());
576+
result.key_grouping = identity_key_grouping("country");
500577
for (int64_t i = 0; i < static_cast<int64_t>(kCountries.size()); ++i) {
501578
vgi::ScanSplit split;
502579
split.payload = encode_range(i, rows);
503580
split.estimated_rows = rows;
504581
split.rows_exact = true;
582+
split.key_value = partition_key_value(kCountries[static_cast<size_t>(i)], key_mode);
505583
result.splits.push_back(std::move(split));
506584
}
507585
return result;

0 commit comments

Comments
 (0)