clickhouse-native 0.8.0 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d1bf3fdd8bd132c0d19937f50055f56b5ab55f4bf383fafc63a74131ff435545
4
- data.tar.gz: 4e6f233a2e250ee5c2c6c1e46ebf9a961416b69553aee7c2018afea619c1abab
3
+ metadata.gz: 7e0bcd3868daa1a69af028ff62e4c0104c82ceac165acfa12f40418259d74929
4
+ data.tar.gz: e40d67544c4b9fb99fbf0ecebf655dd572055fc4d8301521cf0958af1a4531c1
5
5
  SHA512:
6
- metadata.gz: a79cba4fd6ad33b75ec2eecadf87ec0e9fc163ff46874b2ad687f6d767405f7357fffe04a1af584a6716d0c1dcc3ba7171b201a46b130c327d87e3b5e04c52ad
7
- data.tar.gz: 7ed472036327f17efceda43eac9f41cf7e6675e267711de5f974b2b75de88fcc5e557e7290ef1b0f00b084573fc4a8a5a88e49875d0b4fb83237302262b418f4
6
+ metadata.gz: ace9d3e809fa558064f42d2ee66bce667f8514fb06f88d2eb2e24c09f244994e32365acae4f3a3c110025f6a3de947a242d766a72fa72dfaa560fbaf8825c9a0
7
+ data.tar.gz: a935ba30d5f897254492157e82bf98be08e202cd8b619de923c43b0b25ae07f3112d98b20768152dcd44c605eb57db7220e70c240e318415c9992bfb7bd8bf1b
@@ -694,6 +694,38 @@ static CompressionMethod kwarg_compression(VALUE kwargs) {
694
694
  rb_id2name(sym));
695
695
  }
696
696
 
697
+ // Stringify a Ruby setting value for the binary protocol's QuerySettings
698
+ // payload (which is wire-string-typed). Bool maps to "1"/"0" the way the
699
+ // HTTP gem rendered it; everything else goes through #to_s.
700
+ static std::string stringify_setting_value(VALUE v) {
701
+ if (v == Qtrue) return "1";
702
+ if (v == Qfalse) return "0";
703
+ VALUE s = rb_funcall(v, rb_intern("to_s"), 0);
704
+ StringValue(s);
705
+ return std::string(RSTRING_PTR(s), RSTRING_LEN(s));
706
+ }
707
+
708
+ static int apply_settings_cb(VALUE key, VALUE val, VALUE arg) {
709
+ auto* q = reinterpret_cast<Query*>(arg);
710
+ VALUE k = SYMBOL_P(key) ? rb_sym2str(key) : key;
711
+ StringValue(k);
712
+ q->SetSetting(
713
+ std::string(RSTRING_PTR(k), RSTRING_LEN(k)),
714
+ QuerySettingsField{stringify_setting_value(val), 0});
715
+ return ST_CONTINUE;
716
+ }
717
+
718
+ // Read a `settings:` Hash out of the parsed kwargs and stamp each entry
719
+ // onto `q` as a per-query setting. No-op if kwargs is nil or settings is
720
+ // missing/empty. Raises TypeError if settings is not a Hash.
721
+ static void apply_settings(Query& q, VALUE kwargs) {
722
+ if (NIL_P(kwargs)) return;
723
+ VALUE settings = rb_hash_lookup2(kwargs, ID2SYM(rb_intern("settings")), Qnil);
724
+ if (NIL_P(settings)) return;
725
+ Check_Type(settings, T_HASH);
726
+ rb_hash_foreach(settings, apply_settings_cb, reinterpret_cast<VALUE>(&q));
727
+ }
728
+
697
729
  // Client.new(host:, port:, database:, user:, password:)
698
730
  static VALUE ch_client_initialize(int argc, VALUE* argv, VALUE self) {
699
731
  VALUE kwargs = Qnil;
@@ -734,7 +766,7 @@ static VALUE ch_client_initialize(int argc, VALUE* argv, VALUE self) {
734
766
  namespace {
735
767
  struct ExecuteNoGVL {
736
768
  Client* client;
737
- std::string sql;
769
+ const Query* query;
738
770
  std::exception_ptr err;
739
771
  };
740
772
  } // namespace
@@ -742,7 +774,7 @@ struct ExecuteNoGVL {
742
774
  static void* execute_no_gvl(void* data) {
743
775
  auto* a = static_cast<ExecuteNoGVL*>(data);
744
776
  try {
745
- a->client->Execute(Query(a->sql));
777
+ a->client->Execute(*a->query);
746
778
  } catch (...) {
747
779
  a->err = std::current_exception();
748
780
  }
@@ -756,12 +788,17 @@ static void execute_unblock(void* data) {
756
788
  try { a->client->ResetConnection(); } catch (...) {}
757
789
  }
758
790
 
759
- static VALUE ch_client_execute(VALUE self, VALUE rb_sql) {
791
+ static VALUE ch_client_execute(int argc, VALUE* argv, VALUE self) {
792
+ VALUE rb_sql, kwargs = Qnil;
793
+ rb_scan_args(argc, argv, "1:", &rb_sql, &kwargs);
760
794
  Check_Type(rb_sql, T_STRING);
761
795
  CHClient* c = as_client(self);
762
796
  if (!c->client) rb_raise(err_connection, "clickhouse-native: client is closed");
763
797
 
764
- ExecuteNoGVL args{c->client.get(), std::string(StringValueCStr(rb_sql)), nullptr};
798
+ Query q(std::string(RSTRING_PTR(rb_sql), RSTRING_LEN(rb_sql)));
799
+ apply_settings(q, kwargs);
800
+
801
+ ExecuteNoGVL args{c->client.get(), &q, nullptr};
765
802
  rb_thread_call_without_gvl(execute_no_gvl, &args, execute_unblock, &args);
766
803
  if (args.err) {
767
804
  // clickhouse-cpp may leave the read stream partially consumed when the
@@ -779,16 +816,19 @@ static VALUE ch_client_execute(VALUE self, VALUE rb_sql) {
779
816
  // See query_each below for a streaming, GVL-releasing variant.
780
817
  // ------------------------------------------------------------------
781
818
 
782
- static VALUE ch_client_query(VALUE self, VALUE rb_sql) {
819
+ static VALUE ch_client_query(int argc, VALUE* argv, VALUE self) {
820
+ VALUE rb_sql, kwargs = Qnil;
821
+ rb_scan_args(argc, argv, "1:", &rb_sql, &kwargs);
783
822
  Check_Type(rb_sql, T_STRING);
784
823
  CHClient* c = as_client(self);
785
824
  if (!c->client) rb_raise(err_connection, "clickhouse-native: client is closed");
786
825
 
787
- std::string sql(StringValueCStr(rb_sql));
788
826
  VALUE rows = rb_ary_new();
789
827
  try {
790
828
  std::vector<ID> col_ids;
791
- c->client->Select(sql, [&](const Block& block) {
829
+ Query q(std::string(RSTRING_PTR(rb_sql), RSTRING_LEN(rb_sql)));
830
+ apply_settings(q, kwargs);
831
+ q.OnData([&](const Block& block) {
792
832
  size_t ncols = block.GetColumnCount();
793
833
  size_t nrows = block.GetRowCount();
794
834
  if (nrows == 0) return;
@@ -808,6 +848,7 @@ static VALUE ch_client_query(VALUE self, VALUE rb_sql) {
808
848
  rb_ary_push(rows, h);
809
849
  }
810
850
  });
851
+ c->client->Execute(q);
811
852
  return rows;
812
853
  } catch (const std::exception& e) {
813
854
  try { c->client->ResetConnection(); } catch (...) {}
@@ -820,21 +861,25 @@ static VALUE ch_client_query(VALUE self, VALUE rb_sql) {
820
861
  // query_value — returns the first cell of the first row, or nil
821
862
  // ------------------------------------------------------------------
822
863
 
823
- static VALUE ch_client_query_value(VALUE self, VALUE rb_sql) {
864
+ static VALUE ch_client_query_value(int argc, VALUE* argv, VALUE self) {
865
+ VALUE rb_sql, kwargs = Qnil;
866
+ rb_scan_args(argc, argv, "1:", &rb_sql, &kwargs);
824
867
  Check_Type(rb_sql, T_STRING);
825
868
  CHClient* c = as_client(self);
826
869
  if (!c->client) rb_raise(err_connection, "clickhouse-native: client is closed");
827
870
 
828
- std::string sql(StringValueCStr(rb_sql));
829
871
  try {
830
872
  VALUE out = Qnil;
831
873
  bool seen = false;
832
- c->client->Select(sql, [&](const Block& block) {
874
+ Query q(std::string(RSTRING_PTR(rb_sql), RSTRING_LEN(rb_sql)));
875
+ apply_settings(q, kwargs);
876
+ q.OnData([&](const Block& block) {
833
877
  if (seen) return;
834
878
  if (block.GetRowCount() == 0 || block.GetColumnCount() == 0) return;
835
879
  out = value_at(block[0], 0, block.GetColumnType(0));
836
880
  seen = true;
837
881
  });
882
+ c->client->Execute(q);
838
883
  return out;
839
884
  } catch (const std::exception& e) {
840
885
  try { c->client->ResetConnection(); } catch (...) {}
@@ -958,7 +1003,7 @@ struct YieldBlockArgs {
958
1003
 
959
1004
  struct QueryEachNoGVL {
960
1005
  Client* client;
961
- std::string sql;
1006
+ const Query* query;
962
1007
  QueryEachState* state;
963
1008
  std::exception_ptr err;
964
1009
  };
@@ -1003,12 +1048,7 @@ static void* with_gvl_yield(void* data) {
1003
1048
  static void* query_each_no_gvl(void* data) {
1004
1049
  auto* a = static_cast<QueryEachNoGVL*>(data);
1005
1050
  try {
1006
- a->client->SelectCancelable(a->sql, [&](const Block& block) -> bool {
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
- });
1051
+ a->client->Execute(*a->query);
1012
1052
  } catch (...) {
1013
1053
  a->err = std::current_exception();
1014
1054
  }
@@ -1021,19 +1061,24 @@ static void query_each_unblock(void* data) {
1021
1061
  try { a->client->ResetConnection(); } catch (...) {}
1022
1062
  }
1023
1063
 
1024
- static VALUE ch_client_query_each(VALUE self, VALUE rb_sql) {
1064
+ static VALUE ch_client_query_each(int argc, VALUE* argv, VALUE self) {
1025
1065
  rb_need_block();
1066
+ VALUE rb_sql, kwargs = Qnil;
1067
+ rb_scan_args(argc, argv, "1:", &rb_sql, &kwargs);
1026
1068
  Check_Type(rb_sql, T_STRING);
1027
1069
  CHClient* c = as_client(self);
1028
1070
  if (!c->client) rb_raise(err_connection, "clickhouse-native: client is closed");
1029
1071
 
1030
1072
  QueryEachState state{rb_block_proc(), {}, 0, false};
1031
- QueryEachNoGVL args{
1032
- c->client.get(),
1033
- std::string(RSTRING_PTR(rb_sql), RSTRING_LEN(rb_sql)),
1034
- &state,
1035
- nullptr,
1036
- };
1073
+ Query q(std::string(RSTRING_PTR(rb_sql), RSTRING_LEN(rb_sql)));
1074
+ apply_settings(q, kwargs);
1075
+ q.OnDataCancelable([&state](const Block& block) -> bool {
1076
+ if (state.aborted) return false;
1077
+ YieldBlockArgs ya{&block, &state};
1078
+ rb_thread_call_with_gvl(with_gvl_yield, &ya);
1079
+ return !state.aborted;
1080
+ });
1081
+ QueryEachNoGVL args{c->client.get(), &q, &state, nullptr};
1037
1082
 
1038
1083
  rb_thread_call_without_gvl(query_each_no_gvl, &args, query_each_unblock, &args);
1039
1084
 
@@ -1139,13 +1184,13 @@ extern "C" void Init_clickhouse_native(void) {
1139
1184
  rb_define_method(rb_cClient, "initialize",
1140
1185
  reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_initialize), -1);
1141
1186
  rb_define_method(rb_cClient, "execute",
1142
- reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_execute), 1);
1187
+ reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_execute), -1);
1143
1188
  rb_define_method(rb_cClient, "query",
1144
- reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query), 1);
1189
+ reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query), -1);
1145
1190
  rb_define_method(rb_cClient, "query_value",
1146
- reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query_value), 1);
1191
+ reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query_value), -1);
1147
1192
  rb_define_method(rb_cClient, "query_each",
1148
- reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query_each), 1);
1193
+ reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_query_each), -1);
1149
1194
  rb_define_method(rb_cClient, "insert_block",
1150
1195
  reinterpret_cast<VALUE (*)(ANYARGS)>(ch_client_insert_block), 3);
1151
1196
  rb_define_method(rb_cClient, "ping",
@@ -12,19 +12,19 @@ module ClickhouseNative
12
12
  module Logging
13
13
  LEVEL = :debug
14
14
 
15
- def execute(sql)
15
+ def execute(sql, **opts)
16
16
  log_sql(sql) { super }
17
17
  end
18
18
 
19
- def query(sql)
19
+ def query(sql, **opts)
20
20
  log_sql(sql) { super }
21
21
  end
22
22
 
23
- def query_value(sql)
23
+ def query_value(sql, **opts)
24
24
  log_sql(sql) { super }
25
25
  end
26
26
 
27
- def query_each(sql, &)
27
+ def query_each(sql, **opts, &)
28
28
  log_sql(sql) { super }
29
29
  end
30
30
 
@@ -53,20 +53,20 @@ module ClickhouseNative
53
53
  end
54
54
  end
55
55
 
56
- def execute(sql)
57
- with { |c| c.execute(sql) }
56
+ def execute(sql, **opts)
57
+ with { |c| c.execute(sql, **opts) }
58
58
  end
59
59
 
60
- def query(sql)
61
- with { |c| c.query(sql) }
60
+ def query(sql, **opts)
61
+ with { |c| c.query(sql, **opts) }
62
62
  end
63
63
 
64
- def query_each(sql, &block)
65
- with { |c| c.query_each(sql, &block) }
64
+ def query_each(sql, **opts, &block)
65
+ with { |c| c.query_each(sql, **opts, &block) }
66
66
  end
67
67
 
68
- def query_value(sql)
69
- with { |c| c.query_value(sql) }
68
+ def query_value(sql, **opts)
69
+ with { |c| c.query_value(sql, **opts) }
70
70
  end
71
71
 
72
72
  def insert(table, rows, **opts)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ClickhouseNative
4
- VERSION = "0.8.0"
4
+ VERSION = "0.9.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clickhouse-native
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuri Smirnov
@@ -310,7 +310,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
310
310
  - !ruby/object:Gem::Version
311
311
  version: '0'
312
312
  requirements: []
313
- rubygems_version: 4.0.6
313
+ rubygems_version: 4.0.10
314
314
  specification_version: 4
315
315
  summary: ClickHouse Ruby driver over the native TCP protocol
316
316
  test_files: []