clickhouse-native 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/clickhouse_native/client.cpp +112 -28
- data/ext/clickhouse_native/extconf.rb +30 -3
- data/ext/clickhouse_native/vendor/clickhouse-cpp/.github/workflows/bazel.yml +120 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/.github/workflows/cross-repo-bug-relay.yml +17 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/.github/workflows/linux.yml +22 -23
- data/ext/clickhouse_native/vendor/clickhouse-cpp/.github/workflows/macos.yml +22 -21
- data/ext/clickhouse_native/vendor/clickhouse-cpp/.github/workflows/windows_mingw.yml +29 -36
- data/ext/clickhouse_native/vendor/clickhouse-cpp/.github/workflows/windows_msvc.yml +29 -36
- data/ext/clickhouse_native/vendor/clickhouse-cpp/.gitignore +6 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/AI_POLICY.md +13 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/BUILD.bazel +167 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/CMakeLists.txt +2 -1
- data/ext/clickhouse_native/vendor/clickhouse-cpp/MODULE.bazel +17 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/MODULE.bazel.lock +503 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/README.md +32 -6
- data/ext/clickhouse_native/vendor/clickhouse-cpp/ci/docker-compose/config.xml +53 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/ci/docker-compose/users.xml +35 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/ci/docker-compose.yml +22 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/CMakeLists.txt +11 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/base/sslsocket.cpp +24 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/block.cpp +1 -1
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/block.h +2 -1
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/client.cpp +293 -136
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/client.h +31 -2
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/array.cpp +12 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/array.h +17 -7
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/bool.cpp +79 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/bool.h +62 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/factory.cpp +16 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/itemview.cpp +2 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/itemview.h +6 -2
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/json.cpp +102 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/json.h +82 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/lowcardinality.cpp +2 -1
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/string.cpp +7 -2
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/tuple.cpp +48 -5
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/columns/tuple.h +14 -1
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/query.h +2 -2
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/server_exception.h +0 -3
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/types/type_parser.cpp +43 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/types/type_parser.h +9 -0
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/types/types.cpp +61 -11
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/types/types.h +18 -2
- data/ext/clickhouse_native/vendor/clickhouse-cpp/clickhouse/version.h +1 -1
- data/lib/clickhouse_native/logging.rb +4 -4
- data/lib/clickhouse_native/pool.rb +8 -8
- data/lib/clickhouse_native/version.rb +1 -1
- data/lib/clickhouse_native.rb +1 -0
- metadata +15 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d3e2cb4cbe829d9afd7e30e0ac29ea828020896c93634852b4baef007348d3b0
|
|
4
|
+
data.tar.gz: e5f13079f4de6e64e545f49736a8da6832de954dfe82f1a4d105dd1228680887
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9998240b8ca84a4d28ad1fb956c0bf92e1893d4a9ce024fa443eefaa01efb35b657b55d8c2ce92718fd9224a5167fe0201a955f7147ab7499560a331906e2567
|
|
7
|
+
data.tar.gz: d097a39e1fa03b051a30fe1fb273a928b7e2e555e05945d32b22a9dd9dc1deaf280193b80ecae146d7d442d513bbfb6e638ba4b63589f5a58171ce4b25ba5b87
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include <clickhouse/columns/decimal.h>
|
|
8
8
|
#include <clickhouse/columns/enum.h>
|
|
9
9
|
#include <clickhouse/columns/factory.h>
|
|
10
|
+
#include <clickhouse/columns/json.h>
|
|
10
11
|
#include <clickhouse/columns/lowcardinality.h>
|
|
11
12
|
#include <clickhouse/columns/map.h>
|
|
12
13
|
#include <clickhouse/columns/numeric.h>
|
|
@@ -188,6 +189,17 @@ static VALUE value_at(const ColumnRef& col, size_t idx, const std::string& decla
|
|
|
188
189
|
return rb_utf8_str_new(sv.data(), sv.size());
|
|
189
190
|
}
|
|
190
191
|
|
|
192
|
+
case Type::JSON: {
|
|
193
|
+
// clickhouse-cpp's ColumnJSON is string-backed (it relies on the
|
|
194
|
+
// server's output_format_native_write_json_as_string). Decode the
|
|
195
|
+
// raw JSON text into a Ruby object so a JSON column reads back like
|
|
196
|
+
// Map does — a Hash — rather than a string the caller must re-parse.
|
|
197
|
+
auto sv = col->As<ColumnJSON>()->At(idx);
|
|
198
|
+
VALUE str = rb_utf8_str_new(sv.data(), sv.size());
|
|
199
|
+
VALUE rb_mJSON = rb_const_get(rb_cObject, rb_intern("JSON"));
|
|
200
|
+
return rb_funcall(rb_mJSON, rb_intern("parse"), 1, str);
|
|
201
|
+
}
|
|
202
|
+
|
|
191
203
|
case Type::Date: {
|
|
192
204
|
// Return a Ruby Date so as_json/to_s gives "YYYY-MM-DD" instead of
|
|
193
205
|
// a full ISO8601 timestamp. CH Date is days since 1970-01-01 UTC.
|
|
@@ -327,6 +339,8 @@ static void append_default(const ColumnRef& col) {
|
|
|
327
339
|
case Type::Float64: col->As<ColumnFloat64>()->Append(0); return;
|
|
328
340
|
case Type::String: col->As<ColumnString>()->Append(std::string_view()); return;
|
|
329
341
|
case Type::FixedString: col->As<ColumnFixedString>()->Append(std::string_view()); return;
|
|
342
|
+
// CH rejects an empty string as JSON; the empty value is "{}".
|
|
343
|
+
case Type::JSON: col->As<ColumnJSON>()->Append(std::string_view("{}")); return;
|
|
330
344
|
case Type::Date: col->As<ColumnDate>()->Append(0); return;
|
|
331
345
|
case Type::Date32: col->As<ColumnDate32>()->Append(0); return;
|
|
332
346
|
case Type::DateTime: col->As<ColumnDateTime>()->Append(0); return;
|
|
@@ -490,6 +504,19 @@ static void append_value(const ColumnRef& col, VALUE value) {
|
|
|
490
504
|
return;
|
|
491
505
|
}
|
|
492
506
|
|
|
507
|
+
case Type::JSON: {
|
|
508
|
+
// A String is taken as already-serialized JSON text and passed
|
|
509
|
+
// through verbatim; anything else (Hash / Array / ...) is rendered
|
|
510
|
+
// via #to_json. nil is handled earlier via append_default ("{}").
|
|
511
|
+
VALUE str = RB_TYPE_P(value, T_STRING)
|
|
512
|
+
? value
|
|
513
|
+
: rb_funcall(value, rb_intern("to_json"), 0);
|
|
514
|
+
StringValue(str);
|
|
515
|
+
col->As<ColumnJSON>()->Append(
|
|
516
|
+
std::string_view(RSTRING_PTR(str), RSTRING_LEN(str)));
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
|
|
493
520
|
case Type::Date: col->As<ColumnDate>()->Append(static_cast<std::time_t>(coerce_to_date_epoch(value))); return;
|
|
494
521
|
case Type::Date32: col->As<ColumnDate32>()->Append(static_cast<std::time_t>(coerce_to_date_epoch(value))); return;
|
|
495
522
|
case Type::DateTime: {
|
|
@@ -694,6 +721,50 @@ static CompressionMethod kwarg_compression(VALUE kwargs) {
|
|
|
694
721
|
rb_id2name(sym));
|
|
695
722
|
}
|
|
696
723
|
|
|
724
|
+
// Stringify a Ruby setting value for the binary protocol's QuerySettings
|
|
725
|
+
// payload (which is wire-string-typed). Bool maps to "1"/"0" the way the
|
|
726
|
+
// HTTP gem rendered it; everything else goes through #to_s.
|
|
727
|
+
static std::string stringify_setting_value(VALUE v) {
|
|
728
|
+
if (v == Qtrue) return "1";
|
|
729
|
+
if (v == Qfalse) return "0";
|
|
730
|
+
VALUE s = rb_funcall(v, rb_intern("to_s"), 0);
|
|
731
|
+
StringValue(s);
|
|
732
|
+
return std::string(RSTRING_PTR(s), RSTRING_LEN(s));
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
static int apply_settings_cb(VALUE key, VALUE val, VALUE arg) {
|
|
736
|
+
auto* q = reinterpret_cast<Query*>(arg);
|
|
737
|
+
VALUE k = SYMBOL_P(key) ? rb_sym2str(key) : key;
|
|
738
|
+
StringValue(k);
|
|
739
|
+
q->SetSetting(
|
|
740
|
+
std::string(RSTRING_PTR(k), RSTRING_LEN(k)),
|
|
741
|
+
QuerySettingsField{stringify_setting_value(val), 0});
|
|
742
|
+
return ST_CONTINUE;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// Read a `settings:` Hash out of the parsed kwargs and stamp each entry
|
|
746
|
+
// onto `q` as a per-query setting. No-op if kwargs is nil or settings is
|
|
747
|
+
// missing/empty. Raises TypeError if settings is not a Hash.
|
|
748
|
+
static void apply_settings(Query& q, VALUE kwargs) {
|
|
749
|
+
if (NIL_P(kwargs)) return;
|
|
750
|
+
VALUE settings = rb_hash_lookup2(kwargs, ID2SYM(rb_intern("settings")), Qnil);
|
|
751
|
+
if (NIL_P(settings)) return;
|
|
752
|
+
Check_Type(settings, T_HASH);
|
|
753
|
+
rb_hash_foreach(settings, apply_settings_cb, reinterpret_cast<VALUE>(&q));
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// Same as apply_settings, but first defaults
|
|
757
|
+
// output_format_native_write_json_as_string=1 so JSON columns come back as
|
|
758
|
+
// strings (clickhouse-cpp's ColumnJSON can only read them that way). The flag
|
|
759
|
+
// is 0 (not "important"), so servers that don't know the setting ignore it
|
|
760
|
+
// instead of erroring. User-supplied settings are applied afterwards and win,
|
|
761
|
+
// so callers can still override it.
|
|
762
|
+
static void apply_read_settings(Query& q, VALUE kwargs) {
|
|
763
|
+
q.SetSetting("output_format_native_write_json_as_string",
|
|
764
|
+
QuerySettingsField{"1", 0});
|
|
765
|
+
apply_settings(q, kwargs);
|
|
766
|
+
}
|
|
767
|
+
|
|
697
768
|
// Client.new(host:, port:, database:, user:, password:)
|
|
698
769
|
static VALUE ch_client_initialize(int argc, VALUE* argv, VALUE self) {
|
|
699
770
|
VALUE kwargs = Qnil;
|
|
@@ -734,7 +805,7 @@ static VALUE ch_client_initialize(int argc, VALUE* argv, VALUE self) {
|
|
|
734
805
|
namespace {
|
|
735
806
|
struct ExecuteNoGVL {
|
|
736
807
|
Client* client;
|
|
737
|
-
|
|
808
|
+
const Query* query;
|
|
738
809
|
std::exception_ptr err;
|
|
739
810
|
};
|
|
740
811
|
} // namespace
|
|
@@ -742,7 +813,7 @@ struct ExecuteNoGVL {
|
|
|
742
813
|
static void* execute_no_gvl(void* data) {
|
|
743
814
|
auto* a = static_cast<ExecuteNoGVL*>(data);
|
|
744
815
|
try {
|
|
745
|
-
a->client->Execute(
|
|
816
|
+
a->client->Execute(*a->query);
|
|
746
817
|
} catch (...) {
|
|
747
818
|
a->err = std::current_exception();
|
|
748
819
|
}
|
|
@@ -756,12 +827,17 @@ static void execute_unblock(void* data) {
|
|
|
756
827
|
try { a->client->ResetConnection(); } catch (...) {}
|
|
757
828
|
}
|
|
758
829
|
|
|
759
|
-
static VALUE ch_client_execute(VALUE
|
|
830
|
+
static VALUE ch_client_execute(int argc, VALUE* argv, VALUE self) {
|
|
831
|
+
VALUE rb_sql, kwargs = Qnil;
|
|
832
|
+
rb_scan_args(argc, argv, "1:", &rb_sql, &kwargs);
|
|
760
833
|
Check_Type(rb_sql, T_STRING);
|
|
761
834
|
CHClient* c = as_client(self);
|
|
762
835
|
if (!c->client) rb_raise(err_connection, "clickhouse-native: client is closed");
|
|
763
836
|
|
|
764
|
-
|
|
837
|
+
Query q(std::string(RSTRING_PTR(rb_sql), RSTRING_LEN(rb_sql)));
|
|
838
|
+
apply_settings(q, kwargs);
|
|
839
|
+
|
|
840
|
+
ExecuteNoGVL args{c->client.get(), &q, nullptr};
|
|
765
841
|
rb_thread_call_without_gvl(execute_no_gvl, &args, execute_unblock, &args);
|
|
766
842
|
if (args.err) {
|
|
767
843
|
// clickhouse-cpp may leave the read stream partially consumed when the
|
|
@@ -779,16 +855,19 @@ static VALUE ch_client_execute(VALUE self, VALUE rb_sql) {
|
|
|
779
855
|
// See query_each below for a streaming, GVL-releasing variant.
|
|
780
856
|
// ------------------------------------------------------------------
|
|
781
857
|
|
|
782
|
-
static VALUE ch_client_query(VALUE
|
|
858
|
+
static VALUE ch_client_query(int argc, VALUE* argv, VALUE self) {
|
|
859
|
+
VALUE rb_sql, kwargs = Qnil;
|
|
860
|
+
rb_scan_args(argc, argv, "1:", &rb_sql, &kwargs);
|
|
783
861
|
Check_Type(rb_sql, T_STRING);
|
|
784
862
|
CHClient* c = as_client(self);
|
|
785
863
|
if (!c->client) rb_raise(err_connection, "clickhouse-native: client is closed");
|
|
786
864
|
|
|
787
|
-
std::string sql(StringValueCStr(rb_sql));
|
|
788
865
|
VALUE rows = rb_ary_new();
|
|
789
866
|
try {
|
|
790
867
|
std::vector<ID> col_ids;
|
|
791
|
-
|
|
868
|
+
Query q(std::string(RSTRING_PTR(rb_sql), RSTRING_LEN(rb_sql)));
|
|
869
|
+
apply_read_settings(q, kwargs);
|
|
870
|
+
q.OnData([&](const Block& block) {
|
|
792
871
|
size_t ncols = block.GetColumnCount();
|
|
793
872
|
size_t nrows = block.GetRowCount();
|
|
794
873
|
if (nrows == 0) return;
|
|
@@ -808,6 +887,7 @@ static VALUE ch_client_query(VALUE self, VALUE rb_sql) {
|
|
|
808
887
|
rb_ary_push(rows, h);
|
|
809
888
|
}
|
|
810
889
|
});
|
|
890
|
+
c->client->Execute(q);
|
|
811
891
|
return rows;
|
|
812
892
|
} catch (const std::exception& e) {
|
|
813
893
|
try { c->client->ResetConnection(); } catch (...) {}
|
|
@@ -820,21 +900,25 @@ static VALUE ch_client_query(VALUE self, VALUE rb_sql) {
|
|
|
820
900
|
// query_value — returns the first cell of the first row, or nil
|
|
821
901
|
// ------------------------------------------------------------------
|
|
822
902
|
|
|
823
|
-
static VALUE ch_client_query_value(VALUE
|
|
903
|
+
static VALUE ch_client_query_value(int argc, VALUE* argv, VALUE self) {
|
|
904
|
+
VALUE rb_sql, kwargs = Qnil;
|
|
905
|
+
rb_scan_args(argc, argv, "1:", &rb_sql, &kwargs);
|
|
824
906
|
Check_Type(rb_sql, T_STRING);
|
|
825
907
|
CHClient* c = as_client(self);
|
|
826
908
|
if (!c->client) rb_raise(err_connection, "clickhouse-native: client is closed");
|
|
827
909
|
|
|
828
|
-
std::string sql(StringValueCStr(rb_sql));
|
|
829
910
|
try {
|
|
830
911
|
VALUE out = Qnil;
|
|
831
912
|
bool seen = false;
|
|
832
|
-
|
|
913
|
+
Query q(std::string(RSTRING_PTR(rb_sql), RSTRING_LEN(rb_sql)));
|
|
914
|
+
apply_read_settings(q, kwargs);
|
|
915
|
+
q.OnData([&](const Block& block) {
|
|
833
916
|
if (seen) return;
|
|
834
917
|
if (block.GetRowCount() == 0 || block.GetColumnCount() == 0) return;
|
|
835
918
|
out = value_at(block[0], 0, block.GetColumnType(0));
|
|
836
919
|
seen = true;
|
|
837
920
|
});
|
|
921
|
+
c->client->Execute(q);
|
|
838
922
|
return out;
|
|
839
923
|
} catch (const std::exception& e) {
|
|
840
924
|
try { c->client->ResetConnection(); } catch (...) {}
|
|
@@ -958,7 +1042,7 @@ struct YieldBlockArgs {
|
|
|
958
1042
|
|
|
959
1043
|
struct QueryEachNoGVL {
|
|
960
1044
|
Client* client;
|
|
961
|
-
|
|
1045
|
+
const Query* query;
|
|
962
1046
|
QueryEachState* state;
|
|
963
1047
|
std::exception_ptr err;
|
|
964
1048
|
};
|
|
@@ -1003,12 +1087,7 @@ static void* with_gvl_yield(void* data) {
|
|
|
1003
1087
|
static void* query_each_no_gvl(void* data) {
|
|
1004
1088
|
auto* a = static_cast<QueryEachNoGVL*>(data);
|
|
1005
1089
|
try {
|
|
1006
|
-
a->client->
|
|
1007
|
-
if (a->state->aborted) return false;
|
|
1008
|
-
YieldBlockArgs ya{&block, a->state};
|
|
1009
|
-
rb_thread_call_with_gvl(with_gvl_yield, &ya);
|
|
1010
|
-
return !a->state->aborted;
|
|
1011
|
-
});
|
|
1090
|
+
a->client->Execute(*a->query);
|
|
1012
1091
|
} catch (...) {
|
|
1013
1092
|
a->err = std::current_exception();
|
|
1014
1093
|
}
|
|
@@ -1021,19 +1100,24 @@ static void query_each_unblock(void* data) {
|
|
|
1021
1100
|
try { a->client->ResetConnection(); } catch (...) {}
|
|
1022
1101
|
}
|
|
1023
1102
|
|
|
1024
|
-
static VALUE ch_client_query_each(VALUE
|
|
1103
|
+
static VALUE ch_client_query_each(int argc, VALUE* argv, VALUE self) {
|
|
1025
1104
|
rb_need_block();
|
|
1105
|
+
VALUE rb_sql, kwargs = Qnil;
|
|
1106
|
+
rb_scan_args(argc, argv, "1:", &rb_sql, &kwargs);
|
|
1026
1107
|
Check_Type(rb_sql, T_STRING);
|
|
1027
1108
|
CHClient* c = as_client(self);
|
|
1028
1109
|
if (!c->client) rb_raise(err_connection, "clickhouse-native: client is closed");
|
|
1029
1110
|
|
|
1030
1111
|
QueryEachState state{rb_block_proc(), {}, 0, false};
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1112
|
+
Query q(std::string(RSTRING_PTR(rb_sql), RSTRING_LEN(rb_sql)));
|
|
1113
|
+
apply_read_settings(q, kwargs);
|
|
1114
|
+
q.OnDataCancelable([&state](const Block& block) -> bool {
|
|
1115
|
+
if (state.aborted) return false;
|
|
1116
|
+
YieldBlockArgs ya{&block, &state};
|
|
1117
|
+
rb_thread_call_with_gvl(with_gvl_yield, &ya);
|
|
1118
|
+
return !state.aborted;
|
|
1119
|
+
});
|
|
1120
|
+
QueryEachNoGVL args{c->client.get(), &q, &state, nullptr};
|
|
1037
1121
|
|
|
1038
1122
|
rb_thread_call_without_gvl(query_each_no_gvl, &args, query_each_unblock, &args);
|
|
1039
1123
|
|
|
@@ -1139,13 +1223,13 @@ extern "C" void Init_clickhouse_native(void) {
|
|
|
1139
1223
|
rb_define_method(rb_cClient, "initialize",
|
|
1140
1224
|
reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_initialize), -1);
|
|
1141
1225
|
rb_define_method(rb_cClient, "execute",
|
|
1142
|
-
reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_execute), 1);
|
|
1226
|
+
reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_execute), -1);
|
|
1143
1227
|
rb_define_method(rb_cClient, "query",
|
|
1144
|
-
reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query), 1);
|
|
1228
|
+
reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query), -1);
|
|
1145
1229
|
rb_define_method(rb_cClient, "query_value",
|
|
1146
|
-
reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query_value), 1);
|
|
1230
|
+
reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query_value), -1);
|
|
1147
1231
|
rb_define_method(rb_cClient, "query_each",
|
|
1148
|
-
reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query_each), 1);
|
|
1232
|
+
reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query_each), -1);
|
|
1149
1233
|
rb_define_method(rb_cClient, "insert_block",
|
|
1150
1234
|
reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_insert_block), 3);
|
|
1151
1235
|
rb_define_method(rb_cClient, "ping",
|
|
@@ -22,16 +22,39 @@ def fatal(msg)
|
|
|
22
22
|
abort "clickhouse-native: cannot build extension"
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
# Bundler `git:` installs don't fetch submodules unless the Gemfile sets
|
|
26
|
+
# `submodules: true`, which leaves vendor/clickhouse-cpp empty. When we're
|
|
27
|
+
# sitting in a git checkout, fetch it ourselves so the build can proceed
|
|
28
|
+
# without every consumer having to remember that flag. Released gems and
|
|
29
|
+
# `submodules: recursive` checkouts already have the tree, so this is a no-op
|
|
30
|
+
# there.
|
|
31
|
+
unless File.exist?(File.join(VENDOR, "CMakeLists.txt"))
|
|
32
|
+
in_git_checkout = system(
|
|
33
|
+
"git", "-C", EXT_DIR, "rev-parse", "--is-inside-work-tree",
|
|
34
|
+
out: File::NULL, err: File::NULL
|
|
35
|
+
)
|
|
36
|
+
if in_git_checkout
|
|
37
|
+
warn "clickhouse-native: vendored clickhouse-cpp is missing; " \
|
|
38
|
+
"running `git submodule update --init --recursive`…"
|
|
39
|
+
system("git", "-C", EXT_DIR, "submodule", "update", "--init", "--recursive")
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
25
43
|
unless File.exist?(File.join(VENDOR, "CMakeLists.txt"))
|
|
26
44
|
fatal <<~MSG
|
|
27
45
|
clickhouse-cpp submodule not found at:
|
|
28
46
|
#{VENDOR}
|
|
29
47
|
|
|
30
|
-
|
|
48
|
+
Installing from a git source? Bundler skips submodules unless you add
|
|
49
|
+
`submodules: true` to the gem line:
|
|
50
|
+
|
|
51
|
+
gem "clickhouse-native", git: "...", submodules: true
|
|
52
|
+
|
|
53
|
+
From a manual clone, run:
|
|
31
54
|
git submodule update --init --recursive
|
|
32
55
|
|
|
33
|
-
If you see this
|
|
34
|
-
|
|
56
|
+
If you see this while installing a released gem from RubyGems, please
|
|
57
|
+
report a bug — the published .gem should bundle the submodule tree.
|
|
35
58
|
MSG
|
|
36
59
|
end
|
|
37
60
|
|
|
@@ -97,6 +120,10 @@ configure_args = [
|
|
|
97
120
|
"-DBUILD_BENCHMARK=OFF",
|
|
98
121
|
"-DBUILD_TESTS=OFF",
|
|
99
122
|
"-DWITH_OPENSSL=OFF",
|
|
123
|
+
# clickhouse-cpp v2.6.2 added a distinct Bool column; this gem relies on
|
|
124
|
+
# Bool normalising to UInt8 (see the declared-type handling in client.cpp).
|
|
125
|
+
# Pin the upstream default ON so a future default flip can't break us.
|
|
126
|
+
"-DCH_MAP_BOOL_TO_UINT8=ON",
|
|
100
127
|
"-DCMAKE_POSITION_INDEPENDENT_CODE=ON",
|
|
101
128
|
"-DCMAKE_BUILD_TYPE=Release"
|
|
102
129
|
]
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
name: Bazel
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: '0 0 * * 1'
|
|
6
|
+
push:
|
|
7
|
+
branches: [ '*' ]
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: [ master ]
|
|
10
|
+
|
|
11
|
+
release:
|
|
12
|
+
types:
|
|
13
|
+
- published
|
|
14
|
+
- prereleased
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
build:
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
os: [ubuntu-24.04, macos-latest, windows-latest]
|
|
25
|
+
tls: [boringssl, openssl, 'no']
|
|
26
|
+
|
|
27
|
+
runs-on: ${{ matrix.os }}
|
|
28
|
+
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v6
|
|
31
|
+
with:
|
|
32
|
+
fetch-depth: 100
|
|
33
|
+
fetch-tags: true
|
|
34
|
+
|
|
35
|
+
- name: Setup Bazel
|
|
36
|
+
uses: bazel-contrib/setup-bazel@0.15.0
|
|
37
|
+
with:
|
|
38
|
+
bazelisk-cache: true
|
|
39
|
+
disk-cache: true
|
|
40
|
+
repository-cache: true
|
|
41
|
+
|
|
42
|
+
- name: Build project
|
|
43
|
+
run: bazel build //... --@clickhouse-cpp-client//:tls=${{ matrix.tls }}
|
|
44
|
+
|
|
45
|
+
- name: Run unit tests
|
|
46
|
+
run: bazel test //ut:unit_tests --@clickhouse-cpp-client//:tls=${{ matrix.tls }} --test_output=errors
|
|
47
|
+
|
|
48
|
+
# //ut:e2e_tests is tagged `manual`, so `bazel build //...` above
|
|
49
|
+
# skips it; build it explicitly so the run step below doesn't pay
|
|
50
|
+
# for compilation under the running-server timeout.
|
|
51
|
+
- name: Build e2e tests
|
|
52
|
+
run: bazel build //ut:e2e_tests --@clickhouse-cpp-client//:tls=${{ matrix.tls }}
|
|
53
|
+
|
|
54
|
+
# The e2e suite needs a live server on localhost:9000. Each OS starts
|
|
55
|
+
# one the same way the CMake build's per-OS workflows do, since hosted
|
|
56
|
+
# runners can't all run a Linux container the same way:
|
|
57
|
+
# * Linux — docker-compose (linux.yml)
|
|
58
|
+
# * macOS — the native ClickHouse build run as a process (macos.yml)
|
|
59
|
+
# * Windows — the Linux container under WSL2 + podman (windows_msvc.yml)
|
|
60
|
+
- name: Start ClickHouse (Linux, docker-compose)
|
|
61
|
+
if: runner.os == 'Linux'
|
|
62
|
+
uses: hoverkraft-tech/compose-action@v2.0.1
|
|
63
|
+
with:
|
|
64
|
+
compose-file: ci/docker-compose.yml
|
|
65
|
+
down-flags: --volumes
|
|
66
|
+
|
|
67
|
+
- name: Start ClickHouse (macOS, native binary)
|
|
68
|
+
if: runner.os == 'macOS'
|
|
69
|
+
working-directory: ${{ runner.temp }}
|
|
70
|
+
run: |
|
|
71
|
+
curl https://builds.clickhouse.com/25.12/macos-aarch64/clickhouse -o clickhouse
|
|
72
|
+
chmod +x ./clickhouse
|
|
73
|
+
sudo mkdir -p /var/lib/clickhouse /var/log/clickhouse-server
|
|
74
|
+
sudo chown -R "$USER" /var/lib/clickhouse /var/log/clickhouse-server
|
|
75
|
+
nohup ./clickhouse server --config-file="$GITHUB_WORKSPACE/ci/docker-compose/config.xml" > clickhouse.log 2>&1 &
|
|
76
|
+
for i in {1..60}; do
|
|
77
|
+
if curl -fsS http://localhost:8123/ > /dev/null; then
|
|
78
|
+
echo "ClickHouse is ready"
|
|
79
|
+
exit 0
|
|
80
|
+
fi
|
|
81
|
+
sleep 1
|
|
82
|
+
done
|
|
83
|
+
echo "ClickHouse failed to start"
|
|
84
|
+
tail -200 clickhouse.log || true
|
|
85
|
+
exit 1
|
|
86
|
+
|
|
87
|
+
- name: Enable WSL (Windows)
|
|
88
|
+
if: runner.os == 'Windows'
|
|
89
|
+
uses: Vampire/setup-wsl@v5
|
|
90
|
+
with:
|
|
91
|
+
distribution: Ubuntu-24.04
|
|
92
|
+
additional-packages:
|
|
93
|
+
podman
|
|
94
|
+
podman-compose
|
|
95
|
+
|
|
96
|
+
- name: Start ClickHouse (Windows, WSL + podman)
|
|
97
|
+
if: runner.os == 'Windows'
|
|
98
|
+
shell: wsl-bash {0}
|
|
99
|
+
run: |
|
|
100
|
+
cd $(wslpath -u "${{ github.workspace }}/ci/")
|
|
101
|
+
podman-compose up -d
|
|
102
|
+
timeout 60s bash -c \
|
|
103
|
+
'until curl -s -o /dev/null -w "%{http_code}" http://localhost:8123 | grep -q "200"; do sleep 2; done'
|
|
104
|
+
curl -s http://localhost:8123/?query=SELECT%20VERSION%28%29
|
|
105
|
+
|
|
106
|
+
- name: Wait for ClickHouse (Linux)
|
|
107
|
+
if: runner.os == 'Linux'
|
|
108
|
+
run: |
|
|
109
|
+
for i in {1..60}; do
|
|
110
|
+
if curl -fsS http://localhost:8123/ > /dev/null; then
|
|
111
|
+
echo "ClickHouse is ready"
|
|
112
|
+
exit 0
|
|
113
|
+
fi
|
|
114
|
+
sleep 1
|
|
115
|
+
done
|
|
116
|
+
echo "ClickHouse failed to start"
|
|
117
|
+
exit 1
|
|
118
|
+
|
|
119
|
+
- name: Run e2e tests
|
|
120
|
+
run: bazel test //ut:e2e_tests --@clickhouse-cpp-client//:tls=${{ matrix.tls }} --test_output=errors
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: Relay bugs for cross-repo investigation
|
|
2
|
+
|
|
3
|
+
# Relays newly-opened issues to ClickHouse/integrations-ai-playground for
|
|
4
|
+
# cross-repo investigation.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
issues:
|
|
8
|
+
types: [opened]
|
|
9
|
+
|
|
10
|
+
permissions: {}
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
relay:
|
|
14
|
+
uses: ClickHouse/integrations-shared-workflows/.github/workflows/cross-repo-bug-relay.yml@main
|
|
15
|
+
secrets:
|
|
16
|
+
WORKFLOW_AUTH_PUBLIC_APP_ID: ${{ secrets.WORKFLOW_AUTH_PUBLIC_APP_ID }}
|
|
17
|
+
WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY: ${{ secrets.WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY }}
|
|
@@ -15,10 +15,9 @@ on:
|
|
|
15
15
|
|
|
16
16
|
env:
|
|
17
17
|
BUILD_TYPE: Release
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
CLICKHOUSE_SECURE_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }}
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
22
21
|
|
|
23
22
|
jobs:
|
|
24
23
|
build:
|
|
@@ -83,7 +82,7 @@ jobs:
|
|
|
83
82
|
runs-on: ${{matrix.os}}
|
|
84
83
|
|
|
85
84
|
steps:
|
|
86
|
-
- uses: actions/checkout@
|
|
85
|
+
- uses: actions/checkout@v6
|
|
87
86
|
with:
|
|
88
87
|
fetch-depth: 100
|
|
89
88
|
fetch-tags: true
|
|
@@ -96,22 +95,13 @@ jobs:
|
|
|
96
95
|
${{matrix.COMPILER_INSTALL}} \
|
|
97
96
|
${{matrix.DEPENDENCIES_INSTALL}}
|
|
98
97
|
|
|
99
|
-
- name: Install dependencies - Docker
|
|
100
|
-
run: |
|
|
101
|
-
sudo apt remove -y docker docker-engine docker.io containerd runc
|
|
102
|
-
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release
|
|
103
|
-
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
|
104
|
-
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
|
105
|
-
sudo apt update -q
|
|
106
|
-
sudo apt install docker-ce docker-ce-cli containerd.io
|
|
107
|
-
sudo docker run hello-world
|
|
108
|
-
|
|
109
98
|
- name: Configure project
|
|
110
99
|
run: |
|
|
111
100
|
cmake \
|
|
112
101
|
-D CMAKE_C_COMPILER=${{matrix.C_COMPILER}} \
|
|
113
102
|
-D CMAKE_CXX_COMPILER=${{matrix.CXX_COMPILER}} \
|
|
114
103
|
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
|
104
|
+
-D CH_MAP_BOOL_TO_UINT8=OFF \
|
|
115
105
|
-D BUILD_TESTS=ON \
|
|
116
106
|
${{matrix.SSL_CMAKE_OPTION}} \
|
|
117
107
|
${{matrix.DEPENDENCIES_CMAKE_OPTIONS}} \
|
|
@@ -125,15 +115,24 @@ jobs:
|
|
|
125
115
|
--config ${{env.BUILD_TYPE}} \
|
|
126
116
|
--target all
|
|
127
117
|
|
|
128
|
-
- name:
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
docker stats -a --no-stream
|
|
134
|
-
## Check and wait until CH is ready to accept connections
|
|
135
|
-
docker exec clickhouse bash -c 'for i in {1..10}; do echo checking if clickhouse server is started attempt \#$i; if ( grep -q "<Information> Application: Ready for connections." /var/log/clickhouse-server/clickhouse-server.log ); then echo seems like clickhouse server is started; exit 0; fi; sleep 1; done; exit -1'
|
|
118
|
+
- name: Start ClickHouse in Docker
|
|
119
|
+
uses: hoverkraft-tech/compose-action@v2.0.1
|
|
120
|
+
with:
|
|
121
|
+
compose-file: ci/docker-compose.yml
|
|
122
|
+
down-flags: --volumes
|
|
136
123
|
|
|
124
|
+
- name: Check if ClickHouse is available
|
|
125
|
+
run: |
|
|
126
|
+
for i in {1..60}; do
|
|
127
|
+
if curl -fsS http://localhost:8123/ > /dev/null; then
|
|
128
|
+
echo "ClickHouse is ready"
|
|
129
|
+
exit 0
|
|
130
|
+
fi
|
|
131
|
+
sleep 1
|
|
132
|
+
done
|
|
133
|
+
echo "ClickHouse failed to start"
|
|
134
|
+
exit 1
|
|
135
|
+
|
|
137
136
|
- name: Test
|
|
138
137
|
working-directory: ${{github.workspace}}/build/ut
|
|
139
138
|
run: ./clickhouse-cpp-ut
|
|
@@ -14,13 +14,9 @@ on:
|
|
|
14
14
|
|
|
15
15
|
env:
|
|
16
16
|
BUILD_TYPE: Release
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
CLICKHOUSE_SECURE_PORT: 9440
|
|
21
|
-
CLICKHOUSE_SECURE_USER: default
|
|
22
|
-
CLICKHOUSE_SECURE_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }}
|
|
23
|
-
CLICKHOUSE_SECURE_DB: default
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
24
20
|
|
|
25
21
|
jobs:
|
|
26
22
|
build:
|
|
@@ -40,7 +36,7 @@ jobs:
|
|
|
40
36
|
SSL_INSTALL: openssl
|
|
41
37
|
|
|
42
38
|
steps:
|
|
43
|
-
- uses: actions/checkout@
|
|
39
|
+
- uses: actions/checkout@v6
|
|
44
40
|
with:
|
|
45
41
|
fetch-depth: 100
|
|
46
42
|
fetch-tags: true
|
|
@@ -55,6 +51,7 @@ jobs:
|
|
|
55
51
|
run: |
|
|
56
52
|
cmake \
|
|
57
53
|
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
|
54
|
+
-D CH_MAP_BOOL_TO_UINT8=OFF \
|
|
58
55
|
-D BUILD_TESTS=ON \
|
|
59
56
|
${{matrix.SSL_CMAKE_OPTION}} \
|
|
60
57
|
-S ${{github.workspace}} \
|
|
@@ -67,21 +64,25 @@ jobs:
|
|
|
67
64
|
--config ${{env.BUILD_TYPE}} \
|
|
68
65
|
--target all
|
|
69
66
|
|
|
70
|
-
- name:
|
|
71
|
-
|
|
72
|
-
# by tunneling queries to remote tls server
|
|
73
|
-
# (needed because we can't start real clickhouse instance on macOS)
|
|
67
|
+
- name: Install and start ClickHouse
|
|
68
|
+
working-directory: ${{ runner.temp }}
|
|
74
69
|
run: |
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
curl https://builds.clickhouse.com/25.12/macos-aarch64/clickhouse -o clickhouse
|
|
71
|
+
chmod +x ./clickhouse
|
|
72
|
+
sudo mkdir -p /var/lib/clickhouse /var/log/clickhouse-server
|
|
73
|
+
sudo chown -R "$USER" /var/lib/clickhouse /var/log/clickhouse-server
|
|
74
|
+
nohup ./clickhouse server --config-file="$GITHUB_WORKSPACE/ci/docker-compose/config.xml" > clickhouse.log 2>&1 &
|
|
75
|
+
for i in {1..60}; do
|
|
76
|
+
if curl -fsS http://localhost:8123/ > /dev/null; then
|
|
77
|
+
echo "ClickHouse is ready"
|
|
78
|
+
exit 0
|
|
79
|
+
fi
|
|
80
|
+
sleep 1
|
|
81
|
+
done
|
|
82
|
+
echo "ClickHouse failed to start"
|
|
83
|
+
tail -200 clickhouse.log || true
|
|
84
|
+
exit 1
|
|
78
85
|
|
|
79
86
|
- name: Test
|
|
80
87
|
working-directory: ${{github.workspace}}/build/ut
|
|
81
|
-
env:
|
|
82
|
-
# It is impossible to start CH server in docker on macOS due to github actions limitations,
|
|
83
|
-
# so we use remote server to execute tests, some do not allow some features for anonymoust/free users:
|
|
84
|
-
# - system.query_log used by 'Client/ClientCase.Query_ID' and 'Client/ClientCase.ClientName'
|
|
85
|
-
# - system.opentelemetry_span_log is used by 'Client/ClientCase.TracingContext'
|
|
86
|
-
GTEST_FILTER: "-Client/ClientCase.Query_ID*:Client/ClientCase.TracingContext/*:Client/ClientCase.ClientName/*"
|
|
87
88
|
run: ./clickhouse-cpp-ut ${GTEST_FILTER}
|