Skip to content

Commit da20d1f

Browse files
committed
[carnot] Add ClickHouse source and export-sink plan operators
1 parent 9f56ec5 commit da20d1f

16 files changed

Lines changed: 529 additions & 23 deletions

File tree

‎bazel/container_images.bzl‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#
1515
# SPDX-License-Identifier: Apache-2.0
1616

17-
load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
17+
load("@io_bazel_rules_docker//container:container.bzl", "container_pull", "container_image", "container_layer")
1818

1919
# When adding an image here, first add it to scripts/regclient/regbot_deps.yaml
2020
# Once that is in, trigger the github workflow that mirrors the required image
@@ -367,3 +367,12 @@ def stirling_test_images():
367367
repository = "golang_1_22_grpc_server_with_buildinfo",
368368
digest = "sha256:67adba5e8513670fa37bd042862e7844f26239e8d2997ed8c3b0aa527bc04cc3",
369369
)
370+
371+
# ClickHouse server image for testing.
372+
# clickhouse/clickhouse-server:25.7-alpine
373+
container_pull(
374+
name = "clickhouse_server_base_image",
375+
registry = "docker.io",
376+
repository = "clickhouse/clickhouse-server",
377+
digest = "sha256:60c53a520a1caad6555eb6772a8a9c91bb09774c1c7ec87e3371ea3da254eeab",
378+
)

‎src/carnot/carnot.cc‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ Status CarnotImpl::RegisterUDFsInPlanFragment(exec::ExecState* exec_state, plan:
181181
.OnUDTFSource(no_op)
182182
.OnEmptySource(no_op)
183183
.OnOTelSink(no_op)
184+
.OnClickHouseSource(no_op)
185+
.OnClickHouseExportSink(no_op)
184186
.Walk(pf);
185187
}
186188

‎src/carnot/exec/BUILD.bazel‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pl_cc_library(
4646
"//src/shared/types:cc_library",
4747
"//src/table_store/table:cc_library",
4848
"@com_github_apache_arrow//:arrow",
49+
"@com_github_clickhouse_clickhouse_cpp//:clickhouse_cpp",
4950
"@com_github_grpc_grpc//:grpc++",
5051
"@com_github_opentelemetry_proto//:logs_service_grpc_cc",
5152
"@com_github_opentelemetry_proto//:metrics_service_grpc_cc",
@@ -300,3 +301,46 @@ pl_cc_test(
300301
"@com_github_grpc_grpc//:grpc++_test",
301302
],
302303
)
304+
305+
pl_cc_test(
306+
name = "clickhouse_source_node_test",
307+
timeout = "long",
308+
srcs = ["clickhouse_source_node_test.cc"],
309+
data = [
310+
"//src/stirling/source_connectors/socket_tracer/testing/container_images/clickhouse",
311+
],
312+
tags = [
313+
"exclusive",
314+
"requires_bpf",
315+
],
316+
deps = [
317+
":cc_library",
318+
":exec_node_test_helpers",
319+
":test_utils",
320+
"//src/carnot/planpb:plan_testutils",
321+
"//src/common/testing/test_utils:cc_library",
322+
"@com_github_clickhouse_clickhouse_cpp//:clickhouse_cpp",
323+
],
324+
)
325+
326+
pl_cc_test(
327+
name = "clickhouse_export_sink_node_test",
328+
timeout = "long",
329+
srcs = ["clickhouse_export_sink_node_test.cc"],
330+
data = [
331+
"//src/stirling/source_connectors/socket_tracer/testing/container_images/clickhouse",
332+
],
333+
tags = [
334+
"exclusive",
335+
"requires_bpf",
336+
],
337+
deps = [
338+
":cc_library",
339+
":exec_node_test_helpers",
340+
":test_utils",
341+
"//src/carnot/plan:cc_library",
342+
"//src/carnot/planpb:plan_pl_cc_proto",
343+
"//src/common/testing/test_utils:cc_library",
344+
"@com_github_clickhouse_clickhouse_cpp//:clickhouse_cpp",
345+
],
346+
)

‎src/carnot/exec/exec_graph.cc‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include <unordered_map>
2525

2626
#include "src/carnot/exec/agg_node.h"
27+
#include "src/carnot/exec/clickhouse_export_sink_node.h"
28+
#include "src/carnot/exec/clickhouse_source_node.h"
2729
#include "src/carnot/exec/empty_source_node.h"
2830
#include "src/carnot/exec/equijoin_node.h"
2931
#include "src/carnot/exec/exec_node.h"
@@ -108,6 +110,14 @@ Status ExecutionGraph::Init(table_store::schema::Schema* schema, plan::PlanState
108110
.OnOTelSink([&](auto& node) {
109111
return OnOperatorImpl<plan::OTelExportSinkOperator, OTelExportSinkNode>(node, &descriptors);
110112
})
113+
.OnClickHouseSource([&](auto& node) {
114+
return OnOperatorImpl<plan::ClickHouseSourceOperator, ClickHouseSourceNode>(node,
115+
&descriptors);
116+
})
117+
.OnClickHouseExportSink([&](auto& node) {
118+
return OnOperatorImpl<plan::ClickHouseExportSinkOperator, ClickHouseExportSinkNode>(node,
119+
&descriptors);
120+
})
111121
.Walk(pf_);
112122
}
113123

‎src/carnot/planner/compiler_state/compiler_state.h‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ class CompilerState : public NotCopyable {
119119
int64_t max_output_rows_per_table, std::string_view result_address,
120120
std::string_view result_ssl_targetname, const RedactionOptions& redaction_options,
121121
std::unique_ptr<planpb::OTelEndpointConfig> endpoint_config,
122-
std::unique_ptr<PluginConfig> plugin_config, DebugInfo debug_info)
122+
std::unique_ptr<PluginConfig> plugin_config, DebugInfo debug_info,
123+
std::unique_ptr<planpb::ClickHouseConfig> clickhouse_config = nullptr)
123124
: relation_map_(std::move(relation_map)),
124125
table_names_to_sensitive_columns_(table_names_to_sensitive_columns),
125126
registry_info_(registry_info),
@@ -130,7 +131,8 @@ class CompilerState : public NotCopyable {
130131
redaction_options_(redaction_options),
131132
endpoint_config_(std::move(endpoint_config)),
132133
plugin_config_(std::move(plugin_config)),
133-
debug_info_(std::move(debug_info)) {}
134+
debug_info_(std::move(debug_info)),
135+
clickhouse_config_(std::move(clickhouse_config)) {}
134136

135137
CompilerState() = delete;
136138

@@ -175,6 +177,7 @@ class CompilerState : public NotCopyable {
175177
planpb::OTelEndpointConfig* endpoint_config() { return endpoint_config_.get(); }
176178
PluginConfig* plugin_config() { return plugin_config_.get(); }
177179
const DebugInfo& debug_info() { return debug_info_; }
180+
planpb::ClickHouseConfig* clickhouse_config() { return clickhouse_config_.get(); }
178181

179182
private:
180183
std::unique_ptr<RelationMap> relation_map_;
@@ -191,6 +194,7 @@ class CompilerState : public NotCopyable {
191194
std::unique_ptr<planpb::OTelEndpointConfig> endpoint_config_ = nullptr;
192195
std::unique_ptr<PluginConfig> plugin_config_ = nullptr;
193196
DebugInfo debug_info_;
197+
std::unique_ptr<planpb::ClickHouseConfig> clickhouse_config_ = nullptr;
194198
};
195199

196200
} // namespace planner

‎src/carnot/planner/ir/BUILD.bazel‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pl_cc_library(
4747
"//src/carnot/planpb:plan_pl_cc_proto",
4848
"//src/shared/metadata:cc_library",
4949
"//src/shared/metadatapb:metadata_pl_cc_proto",
50+
"@com_github_clickhouse_clickhouse_cpp//:clickhouse_cpp",
5051
"@com_github_vinzenz_libpypa//:libpypa",
5152
],
5253
)
@@ -67,6 +68,14 @@ pl_cc_test(
6768
],
6869
)
6970

71+
pl_cc_test(
72+
name = "clickhouse_export_sink_ir_test",
73+
srcs = ["clickhouse_export_sink_ir_test.cc"],
74+
deps = [
75+
"//src/carnot/planner/compiler:test_utils",
76+
],
77+
)
78+
7079
pl_cc_test(
7180
name = "pattern_match_test",
7281
srcs = ["pattern_match_test.cc"],

‎src/carnot/planner/ir/all_ir_nodes.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include "src/carnot/planner/ir/blocking_agg_ir.h"
2222
#include "src/carnot/planner/ir/bool_ir.h"
23+
#include "src/carnot/planner/ir/clickhouse_source_ir.h"
24+
#include "src/carnot/planner/ir/clickhouse_export_sink_ir.h"
2325
#include "src/carnot/planner/ir/column_ir.h"
2426
#include "src/carnot/planner/ir/data_ir.h"
2527
#include "src/carnot/planner/ir/drop_ir.h"

‎src/carnot/planner/ir/operators.inl‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,7 @@ PX_CARNOT_IR_NODE(Rolling)
3737
PX_CARNOT_IR_NODE(Stream)
3838
PX_CARNOT_IR_NODE(EmptySource)
3939
PX_CARNOT_IR_NODE(OTelExportSink)
40+
PX_CARNOT_IR_NODE(ClickHouseSource)
41+
PX_CARNOT_IR_NODE(ClickHouseExportSink)
4042

4143
#endif

‎src/carnot/planner/ir/pattern_match.h‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ inline ClassMatch<IRNodeType::kOTelExportSink> OTelExportSink() {
160160
return ClassMatch<IRNodeType::kOTelExportSink>();
161161
}
162162

163+
inline ClassMatch<IRNodeType::kClickHouseExportSink> ClickHouseExportSink() {
164+
return ClassMatch<IRNodeType::kClickHouseExportSink>();
165+
}
166+
163167
inline ClassMatch<IRNodeType::kEmptySource> EmptySource() {
164168
return ClassMatch<IRNodeType::kEmptySource>();
165169
}
@@ -266,7 +270,7 @@ struct ResultSink : public ParentMatch {
266270

267271
bool Match(const IRNode* node) const override {
268272
return ExternalGRPCSink().Match(node) || MemorySink().Match(node) ||
269-
OTelExportSink().Match(node);
273+
OTelExportSink().Match(node) || ClickHouseExportSink().Match(node);
270274
}
271275
};
272276

‎src/carnot/planner/logical_planner.cc‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@ StatusOr<std::unique_ptr<CompilerState>> CreateCompilerState(
9797
for (const auto& debug_info_pb : logical_state.debug_info().otel_debug_attributes()) {
9898
debug_info.otel_debug_attrs.push_back({debug_info_pb.name(), debug_info_pb.value()});
9999
}
100+
101+
std::unique_ptr<planpb::ClickHouseConfig> clickhouse_config = nullptr;
102+
if (logical_state.has_clickhouse_config()) {
103+
clickhouse_config = std::make_unique<planpb::ClickHouseConfig>();
104+
clickhouse_config->set_hostname(logical_state.clickhouse_config().hostname());
105+
clickhouse_config->set_host(logical_state.clickhouse_config().host());
106+
clickhouse_config->set_port(logical_state.clickhouse_config().port());
107+
clickhouse_config->set_username(logical_state.clickhouse_config().username());
108+
clickhouse_config->set_password(logical_state.clickhouse_config().password());
109+
clickhouse_config->set_database(logical_state.clickhouse_config().database());
110+
}
111+
100112
// Create a CompilerState obj using the relation map and grabbing the current time.
101113
return std::make_unique<planner::CompilerState>(
102114
std::move(rel_map), sensitive_columns, registry_info, px::CurrentTimeNS(),
@@ -105,7 +117,8 @@ StatusOr<std::unique_ptr<CompilerState>> CreateCompilerState(
105117
// TODO(philkuz) add an endpoint config to logical_state and pass that in here.
106118
RedactionOptionsFromPb(logical_state.redaction_options()), std::move(otel_endpoint_config),
107119
// TODO(philkuz) propagate the otel debug attributes here.
108-
std::move(plugin_config), debug_info);
120+
std::move(plugin_config), debug_info,
121+
std::move(clickhouse_config));
109122
}
110123

111124
StatusOr<std::unique_ptr<LogicalPlanner>> LogicalPlanner::Create(const udfspb::UDFInfo& udf_info) {

0 commit comments

Comments
 (0)