couchbase 3.1.1-universal-darwin-20 → 3.2.0-universal-darwin-20

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.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/CMakeLists.txt +3 -1
  4. data/ext/build_version.hxx.in +1 -1
  5. data/ext/cmake/Testing.cmake +1 -0
  6. data/ext/cmake/ThirdPartyDependencies.cmake +6 -0
  7. data/ext/cmake/VersionInfo.cmake +3 -0
  8. data/ext/couchbase/bucket.hxx +47 -28
  9. data/ext/couchbase/cbsasl/client.h +1 -1
  10. data/ext/couchbase/cbsasl/context.cc +1 -1
  11. data/ext/couchbase/cbsasl/context.h +3 -3
  12. data/ext/couchbase/cbsasl/mechanism.cc +5 -8
  13. data/ext/couchbase/cbsasl/mechanism.h +1 -4
  14. data/ext/couchbase/cbsasl/plain/plain.cc +1 -1
  15. data/ext/couchbase/cbsasl/scram-sha/scram-sha.cc +30 -36
  16. data/ext/couchbase/cluster.hxx +40 -22
  17. data/ext/couchbase/cluster_options.hxx +7 -1
  18. data/ext/couchbase/configuration.hxx +37 -16
  19. data/ext/couchbase/couchbase.cxx +1145 -291
  20. data/ext/couchbase/error_map.hxx +1 -1
  21. data/ext/couchbase/errors.hxx +25 -17
  22. data/ext/couchbase/io/dns_client.hxx +3 -3
  23. data/ext/couchbase/io/dns_codec.hxx +4 -5
  24. data/ext/couchbase/io/dns_config.hxx +5 -6
  25. data/ext/couchbase/io/dns_message.hxx +3 -3
  26. data/ext/couchbase/io/http_command.hxx +70 -35
  27. data/ext/couchbase/io/http_session.hxx +4 -3
  28. data/ext/couchbase/io/http_session_manager.hxx +28 -19
  29. data/ext/couchbase/io/mcbp_command.hxx +51 -19
  30. data/ext/couchbase/io/mcbp_context.hxx +1 -1
  31. data/ext/couchbase/io/mcbp_parser.hxx +4 -4
  32. data/ext/couchbase/io/mcbp_session.hxx +91 -101
  33. data/ext/couchbase/io/query_cache.hxx +2 -2
  34. data/ext/couchbase/io/retry_orchestrator.hxx +2 -4
  35. data/ext/couchbase/io/retry_reason.hxx +2 -2
  36. data/ext/couchbase/io/retry_strategy.hxx +1 -6
  37. data/ext/couchbase/io/streams.hxx +7 -7
  38. data/ext/couchbase/metrics/logging_meter.hxx +228 -0
  39. data/ext/couchbase/metrics/logging_meter_options.hxx +28 -0
  40. data/ext/couchbase/metrics/meter.hxx +49 -0
  41. data/ext/couchbase/metrics/noop_meter.hxx +43 -0
  42. data/ext/couchbase/operations.hxx +4 -0
  43. data/ext/couchbase/operations/analytics_dataset_create.hxx +16 -12
  44. data/ext/couchbase/operations/analytics_dataset_drop.hxx +11 -11
  45. data/ext/couchbase/operations/analytics_dataset_get_all.hxx +6 -6
  46. data/ext/couchbase/operations/analytics_dataverse_create.hxx +10 -11
  47. data/ext/couchbase/operations/analytics_dataverse_drop.hxx +10 -11
  48. data/ext/couchbase/operations/analytics_get_pending_mutations.hxx +9 -11
  49. data/ext/couchbase/operations/analytics_index_create.hxx +14 -13
  50. data/ext/couchbase/operations/analytics_index_drop.hxx +18 -12
  51. data/ext/couchbase/operations/analytics_index_get_all.hxx +8 -6
  52. data/ext/couchbase/operations/analytics_link.hxx +39 -0
  53. data/ext/couchbase/operations/analytics_link_azure_blob_external.hxx +145 -0
  54. data/ext/couchbase/operations/analytics_link_connect.hxx +14 -12
  55. data/ext/couchbase/operations/analytics_link_couchbase_remote.hxx +220 -0
  56. data/ext/couchbase/operations/analytics_link_create.hxx +128 -0
  57. data/ext/couchbase/operations/analytics_link_disconnect.hxx +11 -12
  58. data/ext/couchbase/operations/analytics_link_drop.hxx +130 -0
  59. data/ext/couchbase/operations/analytics_link_get_all.hxx +160 -0
  60. data/ext/couchbase/operations/analytics_link_replace.hxx +128 -0
  61. data/ext/couchbase/operations/analytics_link_s3_external.hxx +122 -0
  62. data/ext/couchbase/operations/bucket_create.hxx +8 -8
  63. data/ext/couchbase/operations/bucket_drop.hxx +5 -5
  64. data/ext/couchbase/operations/bucket_flush.hxx +5 -5
  65. data/ext/couchbase/operations/bucket_get.hxx +7 -7
  66. data/ext/couchbase/operations/bucket_get_all.hxx +7 -5
  67. data/ext/couchbase/operations/bucket_settings.hxx +40 -49
  68. data/ext/couchbase/operations/bucket_update.hxx +8 -8
  69. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +7 -7
  70. data/ext/couchbase/operations/collection_create.hxx +11 -11
  71. data/ext/couchbase/operations/collection_drop.hxx +12 -10
  72. data/ext/couchbase/operations/collections_manifest_get.hxx +3 -3
  73. data/ext/couchbase/operations/design_document.hxx +2 -2
  74. data/ext/couchbase/operations/document_analytics.hxx +29 -36
  75. data/ext/couchbase/operations/document_append.hxx +3 -3
  76. data/ext/couchbase/operations/document_decrement.hxx +3 -3
  77. data/ext/couchbase/operations/document_exists.hxx +2 -2
  78. data/ext/couchbase/operations/document_get.hxx +3 -3
  79. data/ext/couchbase/operations/document_get_and_lock.hxx +5 -3
  80. data/ext/couchbase/operations/document_get_and_touch.hxx +5 -3
  81. data/ext/couchbase/operations/document_get_projected.hxx +10 -11
  82. data/ext/couchbase/operations/document_increment.hxx +3 -3
  83. data/ext/couchbase/operations/document_insert.hxx +3 -3
  84. data/ext/couchbase/operations/document_lookup_in.hxx +12 -18
  85. data/ext/couchbase/operations/document_mutate_in.hxx +13 -18
  86. data/ext/couchbase/operations/document_prepend.hxx +3 -3
  87. data/ext/couchbase/operations/document_query.hxx +39 -41
  88. data/ext/couchbase/operations/document_remove.hxx +3 -3
  89. data/ext/couchbase/operations/document_replace.hxx +3 -3
  90. data/ext/couchbase/operations/document_search.hxx +56 -61
  91. data/ext/couchbase/operations/document_touch.hxx +3 -3
  92. data/ext/couchbase/operations/document_unlock.hxx +3 -3
  93. data/ext/couchbase/operations/document_upsert.hxx +3 -3
  94. data/ext/couchbase/operations/document_view.hxx +23 -23
  95. data/ext/couchbase/operations/group_drop.hxx +5 -5
  96. data/ext/couchbase/operations/group_get.hxx +7 -7
  97. data/ext/couchbase/operations/group_get_all.hxx +6 -6
  98. data/ext/couchbase/operations/group_upsert.hxx +11 -11
  99. data/ext/couchbase/operations/http_noop.hxx +6 -6
  100. data/ext/couchbase/operations/mcbp_noop.hxx +3 -3
  101. data/ext/couchbase/operations/query_index_build_deferred.hxx +6 -6
  102. data/ext/couchbase/operations/query_index_create.hxx +10 -8
  103. data/ext/couchbase/operations/query_index_drop.hxx +8 -8
  104. data/ext/couchbase/operations/query_index_get_all.hxx +43 -39
  105. data/ext/couchbase/operations/rbac.hxx +40 -63
  106. data/ext/couchbase/operations/role_get_all.hxx +6 -6
  107. data/ext/couchbase/operations/scope_create.hxx +10 -10
  108. data/ext/couchbase/operations/scope_drop.hxx +9 -9
  109. data/ext/couchbase/operations/scope_get_all.hxx +8 -8
  110. data/ext/couchbase/operations/search_get_stats.hxx +5 -3
  111. data/ext/couchbase/operations/search_index.hxx +6 -15
  112. data/ext/couchbase/operations/search_index_analyze_document.hxx +11 -11
  113. data/ext/couchbase/operations/search_index_control_ingest.hxx +9 -9
  114. data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +9 -9
  115. data/ext/couchbase/operations/search_index_control_query.hxx +9 -9
  116. data/ext/couchbase/operations/search_index_drop.hxx +11 -9
  117. data/ext/couchbase/operations/search_index_get.hxx +11 -9
  118. data/ext/couchbase/operations/search_index_get_all.hxx +11 -11
  119. data/ext/couchbase/operations/search_index_get_documents_count.hxx +10 -10
  120. data/ext/couchbase/operations/search_index_get_stats.hxx +10 -8
  121. data/ext/couchbase/operations/search_index_upsert.hxx +12 -10
  122. data/ext/couchbase/operations/user_drop.hxx +5 -5
  123. data/ext/couchbase/operations/user_get.hxx +7 -7
  124. data/ext/couchbase/operations/user_get_all.hxx +6 -6
  125. data/ext/couchbase/operations/user_upsert.hxx +9 -9
  126. data/ext/couchbase/operations/view_index_drop.hxx +10 -10
  127. data/ext/couchbase/operations/view_index_get.hxx +13 -15
  128. data/ext/couchbase/operations/view_index_get_all.hxx +17 -20
  129. data/ext/couchbase/operations/view_index_upsert.hxx +9 -7
  130. data/ext/couchbase/origin.hxx +14 -10
  131. data/ext/couchbase/platform/backtrace.c +1 -1
  132. data/ext/couchbase/platform/base64.cc +5 -5
  133. data/ext/couchbase/platform/base64.h +2 -5
  134. data/ext/couchbase/protocol/client_opcode.hxx +7 -4
  135. data/ext/couchbase/protocol/client_request.hxx +2 -2
  136. data/ext/couchbase/protocol/client_response.hxx +41 -16
  137. data/ext/couchbase/protocol/cmd_append.hxx +17 -16
  138. data/ext/couchbase/protocol/cmd_cluster_map_change_notification.hxx +4 -4
  139. data/ext/couchbase/protocol/cmd_decrement.hxx +10 -11
  140. data/ext/couchbase/protocol/cmd_exists.hxx +12 -15
  141. data/ext/couchbase/protocol/cmd_get.hxx +11 -14
  142. data/ext/couchbase/protocol/cmd_get_and_lock.hxx +10 -12
  143. data/ext/couchbase/protocol/cmd_get_and_touch.hxx +10 -12
  144. data/ext/couchbase/protocol/cmd_get_cluster_config.hxx +13 -18
  145. data/ext/couchbase/protocol/cmd_get_collection_id.hxx +12 -15
  146. data/ext/couchbase/protocol/cmd_get_collections_manifest.hxx +12 -16
  147. data/ext/couchbase/protocol/cmd_get_error_map.hxx +14 -17
  148. data/ext/couchbase/protocol/cmd_hello.hxx +8 -10
  149. data/ext/couchbase/protocol/cmd_increment.hxx +9 -10
  150. data/ext/couchbase/protocol/cmd_insert.hxx +9 -9
  151. data/ext/couchbase/protocol/cmd_lookup_in.hxx +12 -13
  152. data/ext/couchbase/protocol/cmd_mutate_in.hxx +11 -11
  153. data/ext/couchbase/protocol/cmd_noop.hxx +16 -20
  154. data/ext/couchbase/protocol/cmd_prepend.hxx +9 -10
  155. data/ext/couchbase/protocol/cmd_remove.hxx +10 -13
  156. data/ext/couchbase/protocol/cmd_replace.hxx +7 -7
  157. data/ext/couchbase/protocol/cmd_sasl_auth.hxx +8 -10
  158. data/ext/couchbase/protocol/cmd_sasl_list_mechs.hxx +10 -15
  159. data/ext/couchbase/protocol/cmd_sasl_step.hxx +10 -12
  160. data/ext/couchbase/protocol/cmd_select_bucket.hxx +14 -18
  161. data/ext/couchbase/protocol/cmd_touch.hxx +8 -11
  162. data/ext/couchbase/protocol/cmd_unlock.hxx +10 -14
  163. data/ext/couchbase/protocol/cmd_upsert.hxx +8 -8
  164. data/ext/couchbase/protocol/datatype.hxx +3 -3
  165. data/ext/couchbase/protocol/durability_level.hxx +2 -2
  166. data/ext/couchbase/protocol/frame_info_id.hxx +4 -4
  167. data/ext/couchbase/protocol/hello_feature.hxx +2 -2
  168. data/ext/couchbase/protocol/magic.hxx +2 -2
  169. data/ext/couchbase/protocol/server_opcode.hxx +2 -2
  170. data/ext/couchbase/protocol/server_request.hxx +1 -1
  171. data/ext/couchbase/protocol/status.hxx +4 -7
  172. data/ext/couchbase/protocol/unsigned_leb128.h +5 -20
  173. data/ext/couchbase/service_type.hxx +4 -4
  174. data/ext/couchbase/tracing/constants.hxx +261 -0
  175. data/ext/couchbase/tracing/noop_tracer.hxx +50 -0
  176. data/ext/couchbase/tracing/request_tracer.hxx +77 -0
  177. data/ext/couchbase/tracing/threshold_logging_options.hxx +64 -0
  178. data/ext/couchbase/tracing/threshold_logging_tracer.hxx +366 -0
  179. data/ext/couchbase/utils/byteswap.hxx +1 -1
  180. data/ext/couchbase/utils/connection_string.hxx +21 -1
  181. data/ext/couchbase/utils/name_codec.hxx +41 -0
  182. data/ext/couchbase/utils/url_codec.hxx +236 -0
  183. data/ext/couchbase/version.hxx +1 -1
  184. data/ext/test/CMakeLists.txt +1 -0
  185. data/ext/test/test_native_trivial_query.cxx +60 -0
  186. data/ext/third_party/hdr_histogram_c/CMakeLists.txt +84 -0
  187. data/ext/third_party/hdr_histogram_c/COPYING.txt +121 -0
  188. data/ext/third_party/hdr_histogram_c/LICENSE.txt +41 -0
  189. data/ext/third_party/hdr_histogram_c/config.cmake.in +6 -0
  190. data/ext/third_party/hdr_histogram_c/src/CMakeLists.txt +83 -0
  191. data/ext/third_party/hdr_histogram_c/src/hdr_atomic.h +146 -0
  192. data/ext/third_party/hdr_histogram_c/src/hdr_encoding.c +322 -0
  193. data/ext/third_party/hdr_histogram_c/src/hdr_encoding.h +79 -0
  194. data/ext/third_party/hdr_histogram_c/src/hdr_endian.h +116 -0
  195. data/ext/third_party/hdr_histogram_c/src/hdr_histogram.c +1196 -0
  196. data/ext/third_party/hdr_histogram_c/src/hdr_histogram.h +516 -0
  197. data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log.c +1290 -0
  198. data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log.h +236 -0
  199. data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log_no_op.c +171 -0
  200. data/ext/third_party/hdr_histogram_c/src/hdr_interval_recorder.c +227 -0
  201. data/ext/third_party/hdr_histogram_c/src/hdr_interval_recorder.h +109 -0
  202. data/ext/third_party/hdr_histogram_c/src/hdr_malloc.h +19 -0
  203. data/ext/third_party/hdr_histogram_c/src/hdr_tests.h +22 -0
  204. data/ext/third_party/hdr_histogram_c/src/hdr_thread.c +108 -0
  205. data/ext/third_party/hdr_histogram_c/src/hdr_thread.h +55 -0
  206. data/ext/third_party/hdr_histogram_c/src/hdr_time.c +98 -0
  207. data/ext/third_party/hdr_histogram_c/src/hdr_time.h +49 -0
  208. data/ext/third_party/hdr_histogram_c/src/hdr_writer_reader_phaser.c +143 -0
  209. data/ext/third_party/hdr_histogram_c/src/hdr_writer_reader_phaser.h +51 -0
  210. data/lib/couchbase/cluster.rb +1 -0
  211. data/lib/couchbase/errors.rb +3 -0
  212. data/lib/couchbase/libcouchbase.bundle +0 -0
  213. data/lib/couchbase/management/analytics_index_manager.rb +920 -226
  214. data/lib/couchbase/management/bucket_manager.rb +207 -69
  215. data/lib/couchbase/management/collection_manager.rb +173 -61
  216. data/lib/couchbase/management/query_index_manager.rb +357 -169
  217. data/lib/couchbase/options.rb +75 -3
  218. data/lib/couchbase/scope.rb +102 -0
  219. data/lib/couchbase/utils/time.rb +4 -0
  220. data/lib/couchbase/version.rb +6 -6
  221. metadata +48 -5
@@ -17,9 +17,9 @@
17
17
 
18
18
  #pragma once
19
19
 
20
- #include <utility>
21
- #include <thread>
22
20
  #include <fstream>
21
+ #include <thread>
22
+ #include <utility>
23
23
 
24
24
  #include <asio/ssl.hpp>
25
25
 
@@ -32,6 +32,11 @@
32
32
  #include <operations.hxx>
33
33
  #include <operations/document_query.hxx>
34
34
 
35
+ #include <tracing/noop_tracer.hxx>
36
+ #include <tracing/threshold_logging_tracer.hxx>
37
+ #include <metrics/noop_meter.hxx>
38
+ #include <metrics/logging_meter.hxx>
39
+
35
40
  #include <diagnostics.hxx>
36
41
 
37
42
  namespace couchbase
@@ -88,12 +93,9 @@ class cluster
88
93
  {
89
94
  public:
90
95
  explicit cluster(asio::io_context& ctx)
91
- : id_(uuid::to_string(uuid::random()))
92
- , ctx_(ctx)
96
+ : ctx_(ctx)
93
97
  , work_(asio::make_work_guard(ctx_))
94
- , tls_(asio::ssl::context::tls_client)
95
98
  , session_manager_(std::make_shared<io::http_session_manager>(id_, ctx_, tls_))
96
- , dns_config_(io::dns::dns_config::get())
97
99
  , dns_client_(ctx_)
98
100
  {
99
101
  }
@@ -102,6 +104,17 @@ class cluster
102
104
  void open(const couchbase::origin& origin, Handler&& handler)
103
105
  {
104
106
  origin_ = origin;
107
+ if (origin_.options().enable_tracing) {
108
+ tracer_ = new tracing::threshold_logging_tracer(ctx_, origin.options().tracing_options);
109
+ } else {
110
+ tracer_ = new tracing::noop_tracer();
111
+ }
112
+ if (origin_.options().enable_metrics) {
113
+ meter_ = new metrics::logging_meter(ctx_, origin.options().metrics_options);
114
+ } else {
115
+ meter_ = new metrics::noop_meter();
116
+ }
117
+ session_manager_->set_tracer(tracer_);
105
118
  if (origin_.options().enable_dns_srv) {
106
119
  return asio::post(asio::bind_executor(
107
120
  ctx_, [this, handler = std::forward<Handler>(handler)]() mutable { return do_dns_srv(std::forward<Handler>(handler)); }));
@@ -122,21 +135,24 @@ class cluster
122
135
  session_manager_->close();
123
136
  handler();
124
137
  work_.reset();
138
+ delete tracer_;
139
+ tracer_ = nullptr;
140
+ delete meter_;
141
+ meter_ = nullptr;
125
142
  }));
126
143
  }
127
144
 
128
145
  template<typename Handler>
129
146
  void open_bucket(const std::string& bucket_name, Handler&& handler)
130
147
  {
131
- auto ptr = buckets_.find(bucket_name);
132
- if (ptr != buckets_.end()) {
148
+ if (buckets_.find(bucket_name) != buckets_.end()) {
133
149
  return handler({});
134
150
  }
135
151
  std::vector<protocol::hello_feature> known_features;
136
152
  if (session_ && session_->has_config()) {
137
153
  known_features = session_->supported_features();
138
154
  }
139
- auto b = std::make_shared<bucket>(id_, ctx_, tls_, bucket_name, origin_, known_features);
155
+ auto b = std::make_shared<bucket>(id_, ctx_, tls_, tracer_, meter_, bucket_name, origin_, known_features);
140
156
  b->bootstrap([this, handler = std::forward<Handler>(handler)](std::error_code ec, const configuration& config) mutable {
141
157
  if (!ec && !session_->supports_gcccp()) {
142
158
  session_manager_->set_configuration(config, origin_.options());
@@ -153,7 +169,7 @@ class cluster
153
169
  if (bucket == buckets_.end()) {
154
170
  error_context::key_value ctx{};
155
171
  ctx.id = request.id;
156
- ctx.ec = std::make_error_code(error::common_errc::bucket_not_found);
172
+ ctx.ec = error::common_errc::bucket_not_found;
157
173
  using response_type = typename Request::encoded_response_type;
158
174
  return handler(operations::make_response(std::move(ctx), request, response_type{}));
159
175
  }
@@ -166,10 +182,10 @@ class cluster
166
182
  auto session = session_manager_->check_out(Request::type, origin_.credentials());
167
183
  if (!session) {
168
184
  typename Request::error_context_type ctx{};
169
- ctx.ec = std::make_error_code(error::common_errc::service_not_available);
185
+ ctx.ec = error::common_errc::service_not_available;
170
186
  return handler(operations::make_response(std::move(ctx), request, {}));
171
187
  }
172
- auto cmd = std::make_shared<operations::http_command<Request>>(ctx_, request);
188
+ auto cmd = std::make_shared<operations::http_command<Request>>(ctx_, request, tracer_, meter_);
173
189
  cmd->send_to(session, [this, session, handler = std::forward<Handler>(handler)](typename Request::response_type resp) mutable {
174
190
  handler(std::move(resp));
175
191
  session_manager_->check_in(Request::type, session);
@@ -185,10 +201,10 @@ class cluster
185
201
  asio::post(asio::bind_executor(ctx_, [this, report_id, handler = std::forward<Handler>(handler)]() mutable {
186
202
  diag::diagnostics_result res{ report_id.value(), couchbase::sdk_id() };
187
203
  if (session_) {
188
- res.services[service_type::kv].emplace_back(session_->diag_info());
204
+ res.services[service_type::key_value].emplace_back(session_->diag_info());
189
205
  }
190
- for (const auto& bucket : buckets_) {
191
- bucket.second->export_diag_info(res);
206
+ for (const auto& [name, bucket] : buckets_) {
207
+ bucket->export_diag_info(res);
192
208
  }
193
209
  session_manager_->export_diag_info(res);
194
210
  handler(std::move(res));
@@ -204,19 +220,19 @@ class cluster
204
220
  report_id = std::make_optional(uuid::to_string(uuid::random()));
205
221
  }
206
222
  if (services.empty()) {
207
- services = { service_type::kv, service_type::views, service_type::query, service_type::search, service_type::analytics };
223
+ services = { service_type::key_value, service_type::view, service_type::query, service_type::search, service_type::analytics };
208
224
  }
209
225
  asio::post(asio::bind_executor(ctx_, [this, report_id, bucket_name, services, handler = std::move(handler)]() mutable {
210
226
  auto collector = std::make_shared<ping_collector>(report_id.value(), std::move(handler));
211
227
  if (bucket_name) {
212
- if (services.find(service_type::kv) != services.end()) {
228
+ if (services.find(service_type::key_value) != services.end()) {
213
229
  auto bucket = buckets_.find(bucket_name.value());
214
230
  if (bucket != buckets_.end()) {
215
231
  bucket->second->ping(collector);
216
232
  }
217
233
  }
218
234
  } else {
219
- if (services.find(service_type::kv) != services.end()) {
235
+ if (services.find(service_type::key_value) != services.end()) {
220
236
  if (session_) {
221
237
  session_->ping(collector->build_reporter());
222
238
  }
@@ -322,7 +338,7 @@ class cluster
322
338
  origin::node_list nodes;
323
339
  nodes.reserve(config.nodes.size());
324
340
  for (const auto& address : config.nodes) {
325
- auto port = address.port_or(origin_.options().network, service_type::kv, origin_.options().enable_tls, 0);
341
+ auto port = address.port_or(origin_.options().network, service_type::key_value, origin_.options().enable_tls, 0);
326
342
  if (port == 0) {
327
343
  continue;
328
344
  }
@@ -342,15 +358,17 @@ class cluster
342
358
  });
343
359
  }
344
360
 
345
- std::string id_;
361
+ std::string id_{ uuid::to_string(uuid::random()) };
346
362
  asio::io_context& ctx_;
347
363
  asio::executor_work_guard<asio::io_context::executor_type> work_;
348
- asio::ssl::context tls_;
364
+ asio::ssl::context tls_{ asio::ssl::context::tls_client };
349
365
  std::shared_ptr<io::http_session_manager> session_manager_;
350
- io::dns::dns_config& dns_config_;
366
+ io::dns::dns_config& dns_config_{ io::dns::dns_config::get() };
351
367
  couchbase::io::dns::dns_client dns_client_;
352
368
  std::shared_ptr<io::mcbp_session> session_{};
353
369
  std::map<std::string, std::shared_ptr<bucket>> buckets_{};
354
370
  couchbase::origin origin_{};
371
+ tracing::request_tracer* tracer_{ nullptr };
372
+ metrics::meter* meter_{ nullptr };
355
373
  };
356
374
  } // namespace couchbase
@@ -18,6 +18,8 @@
18
18
  #pragma once
19
19
 
20
20
  #include <timeout_defaults.hxx>
21
+ #include <tracing/threshold_logging_options.hxx>
22
+ #include <metrics/logging_meter_options.hxx>
21
23
 
22
24
  namespace couchbase
23
25
  {
@@ -43,14 +45,18 @@ struct cluster_options {
43
45
  bool enable_unordered_execution{ true };
44
46
  bool enable_clustermap_notification{ true };
45
47
  bool enable_compression{ true };
48
+ bool enable_tracing{ true };
49
+ bool enable_metrics{ true };
46
50
  std::string network{ "auto" };
51
+ tracing::threshold_logging_options tracing_options{};
52
+ metrics::logging_meter_options metrics_options{};
47
53
 
48
54
  std::chrono::milliseconds tcp_keep_alive_interval = timeout_defaults::tcp_keep_alive_interval;
49
55
  std::chrono::milliseconds config_poll_interval = timeout_defaults::config_poll_interval;
50
56
  std::chrono::milliseconds config_poll_floor = timeout_defaults::config_poll_floor;
51
57
  std::chrono::milliseconds config_idle_redial_timeout = timeout_defaults::config_idle_redial_timeout;
52
58
 
53
- size_t max_http_connections{ 0 };
59
+ std::size_t max_http_connections{ 0 };
54
60
  std::chrono::milliseconds idle_http_connection_timeout = timeout_defaults::idle_http_connection_timeout;
55
61
  };
56
62
 
@@ -21,13 +21,13 @@
21
21
 
22
22
  #include <gsl/gsl_util>
23
23
 
24
- #include <tao/json.hpp>
24
+ #include <platform/uuid.h>
25
25
  #include <spdlog/spdlog.h>
26
+ #include <tao/json.hpp>
26
27
  #include <utils/crc32.hxx>
27
- #include <platform/uuid.h>
28
28
 
29
- #include <service_type.hxx>
30
29
  #include <capabilities.hxx>
30
+ #include <service_type.hxx>
31
31
 
32
32
  namespace couchbase
33
33
  {
@@ -73,13 +73,13 @@ struct configuration {
73
73
  case service_type::search:
74
74
  return services_tls.search.value_or(default_value);
75
75
 
76
- case service_type::views:
76
+ case service_type::view:
77
77
  return services_tls.views.value_or(default_value);
78
78
 
79
79
  case service_type::management:
80
80
  return services_tls.management.value_or(default_value);
81
81
 
82
- case service_type::kv:
82
+ case service_type::key_value:
83
83
  return services_tls.key_value.value_or(default_value);
84
84
  }
85
85
  }
@@ -93,13 +93,13 @@ struct configuration {
93
93
  case service_type::search:
94
94
  return services_plain.search.value_or(default_value);
95
95
 
96
- case service_type::views:
96
+ case service_type::view:
97
97
  return services_plain.views.value_or(default_value);
98
98
 
99
99
  case service_type::management:
100
100
  return services_plain.management.value_or(default_value);
101
101
 
102
- case service_type::kv:
102
+ case service_type::key_value:
103
103
  return services_plain.key_value.value_or(default_value);
104
104
  }
105
105
  return default_value;
@@ -139,13 +139,13 @@ struct configuration {
139
139
  case service_type::search:
140
140
  return address->second.services_tls.search.value_or(default_value);
141
141
 
142
- case service_type::views:
142
+ case service_type::view:
143
143
  return address->second.services_tls.views.value_or(default_value);
144
144
 
145
145
  case service_type::management:
146
146
  return address->second.services_tls.management.value_or(default_value);
147
147
 
148
- case service_type::kv:
148
+ case service_type::key_value:
149
149
  return address->second.services_tls.key_value.value_or(default_value);
150
150
  }
151
151
  }
@@ -159,13 +159,13 @@ struct configuration {
159
159
  case service_type::search:
160
160
  return address->second.services_plain.search.value_or(default_value);
161
161
 
162
- case service_type::views:
162
+ case service_type::view:
163
163
  return address->second.services_plain.views.value_or(default_value);
164
164
 
165
165
  case service_type::management:
166
166
  return address->second.services_plain.management.value_or(default_value);
167
167
 
168
- case service_type::kv:
168
+ case service_type::key_value:
169
169
  return address->second.services_plain.key_value.value_or(default_value);
170
170
  }
171
171
  return default_value;
@@ -191,7 +191,8 @@ struct configuration {
191
191
 
192
192
  using vbucket_map = typename std::vector<std::vector<std::int16_t>>;
193
193
 
194
- std::optional<std::uint64_t> rev{};
194
+ std::optional<std::int64_t> epoch{};
195
+ std::optional<std::int64_t> rev{};
195
196
  couchbase::uuid::uuid_t id{};
196
197
  std::optional<std::uint32_t> num_replicas{};
197
198
  std::vector<node> nodes{};
@@ -203,8 +204,26 @@ struct configuration {
203
204
  std::set<cluster_capability> cluster_capabilities{};
204
205
  node_locator_type node_locator{ node_locator_type::unknown };
205
206
 
207
+ bool operator==(const configuration& other) const
208
+ {
209
+ return epoch == other.epoch && rev == other.rev;
210
+ }
211
+
212
+ bool operator<(const configuration& other) const
213
+ {
214
+ return epoch < other.epoch && rev < other.rev;
215
+ }
216
+
217
+ bool operator>(const configuration& other) const
218
+ {
219
+ return other < *this;
220
+ }
221
+
206
222
  [[nodiscard]] std::string rev_str() const
207
223
  {
224
+ if (epoch) {
225
+ return fmt::format("{}:{}", epoch.value(), rev.value_or(0));
226
+ }
208
227
  return rev ? fmt::format("{}", *rev) : "(none)";
209
228
  }
210
229
 
@@ -240,8 +259,8 @@ struct configuration {
240
259
  throw std::runtime_error("cannot map key: partition map is not available");
241
260
  }
242
261
  uint32_t crc = utils::hash_crc32(key.data(), key.size());
243
- uint16_t vbucket = uint16_t(crc % vbmap->size());
244
- return std::make_pair(vbucket, vbmap->at(vbucket)[0]);
262
+ auto vbucket = uint16_t(crc % vbmap->size());
263
+ return { vbucket, vbmap->at(vbucket)[0] };
245
264
  }
246
265
  };
247
266
 
@@ -250,6 +269,7 @@ make_blank_configuration(const std::string& hostname, std::uint16_t plain_port,
250
269
  {
251
270
  configuration result;
252
271
  result.id = couchbase::uuid::random();
272
+ result.epoch = 0;
253
273
  result.rev = 0;
254
274
  result.nodes.resize(1);
255
275
  result.nodes[0].hostname = hostname;
@@ -400,7 +420,8 @@ struct traits<couchbase::configuration> {
400
420
  {
401
421
  couchbase::configuration result;
402
422
  result.id = couchbase::uuid::random();
403
- result.rev = v.template optional<std::uint64_t>("rev");
423
+ result.epoch = v.template optional<std::int64_t>("revEpoch");
424
+ result.rev = v.template optional<std::int64_t>("rev");
404
425
  auto* node_locator = v.find("nodeLocator");
405
426
  if (node_locator != nullptr && node_locator->is_string()) {
406
427
  if (node_locator->get_string() == "ketama") {
@@ -423,7 +444,7 @@ struct traits<couchbase::configuration> {
423
444
  const auto& hostname = o.find("hostname");
424
445
  if (hostname != o.end()) {
425
446
  n.hostname = hostname->second.get_string();
426
- n.hostname = n.hostname.substr(0, n.hostname.rfind(":"));
447
+ n.hostname = n.hostname.substr(0, n.hostname.rfind(':'));
427
448
  }
428
449
  const auto& s = o.at("services");
429
450
  n.services_plain.key_value = s.template optional<std::uint16_t>("kv");
@@ -57,6 +57,15 @@ cb_str_new(const std::string& str)
57
57
  return rb_external_str_new(str.data(), static_cast<long>(str.size()));
58
58
  }
59
59
 
60
+ static inline VALUE
61
+ cb_str_new(const std::optional<std::string>& str)
62
+ {
63
+ if (str) {
64
+ return rb_external_str_new(str->data(), static_cast<long>(str->size()));
65
+ }
66
+ return Qnil;
67
+ }
68
+
60
69
  static void
61
70
  init_versions(VALUE mCouchbase)
62
71
  {
@@ -97,11 +106,12 @@ init_versions(VALUE mCouchbase)
97
106
  #endif
98
107
 
99
108
  VALUE version_info = rb_inspect(cb_Version);
100
- spdlog::info("couchbase backend has been initialized: {}",
101
- std::string_view(RSTRING_PTR(version_info), static_cast<std::size_t>(RSTRING_LEN(version_info))));
109
+ spdlog::debug("couchbase backend has been initialized: {}",
110
+ std::string_view(RSTRING_PTR(version_info), static_cast<std::size_t>(RSTRING_LEN(version_info))));
102
111
 
103
112
  VALUE cb_BuildInfo = rb_hash_new();
104
113
  rb_const_set(mCouchbase, rb_intern("BUILD_INFO"), cb_BuildInfo);
114
+ rb_hash_aset(cb_BuildInfo, rb_id2sym(rb_intern("cmake_version")), rb_str_freeze(rb_str_new_cstr(CMAKE_VERSION)));
105
115
  rb_hash_aset(cb_BuildInfo, rb_id2sym(rb_intern("cmake_build_type")), rb_str_freeze(rb_str_new_cstr(CMAKE_BUILD_TYPE)));
106
116
  rb_hash_aset(cb_BuildInfo, rb_id2sym(rb_intern("compile_definitions")), rb_str_freeze(rb_str_new_cstr(BACKEND_COMPILE_DEFINITIONS)));
107
117
  rb_hash_aset(cb_BuildInfo, rb_id2sym(rb_intern("compile_features")), rb_str_freeze(rb_str_new_cstr(BACKEND_COMPILE_FEATURES)));
@@ -235,6 +245,7 @@ static VALUE eInternalServerFailure;
235
245
  static VALUE eInvalidArgument;
236
246
  static VALUE eJobQueueFull;
237
247
  static VALUE eLinkNotFound;
248
+ static VALUE eLinkExists;
238
249
  static VALUE eNumberTooBig;
239
250
  static VALUE eParsingFailure;
240
251
  static VALUE ePathExists;
@@ -317,6 +328,7 @@ init_exceptions(VALUE mCouchbase)
317
328
  eInvalidArgument = rb_define_class_under(mError, "InvalidArgument", rb_eArgError);
318
329
  eJobQueueFull = rb_define_class_under(mError, "JobQueueFull", eCouchbaseError);
319
330
  eLinkNotFound = rb_define_class_under(mError, "LinkNotFound", eCouchbaseError);
331
+ eLinkExists = rb_define_class_under(mError, "LinkExists", eCouchbaseError);
320
332
  eNumberTooBig = rb_define_class_under(mError, "NumberTooBig", eCouchbaseError);
321
333
  eParsingFailure = rb_define_class_under(mError, "ParsingFailure", eCouchbaseError);
322
334
  ePathExists = rb_define_class_under(mError, "PathExists", eCouchbaseError);
@@ -358,7 +370,7 @@ static VALUE
358
370
  cb_map_error_code(std::error_code ec, const std::string& message)
359
371
  {
360
372
  if (ec.category() == couchbase::error::detail::get_common_category()) {
361
- switch (static_cast<couchbase::error::common_errc>(ec.value())) {
373
+ switch (couchbase::error::common_errc(ec.value())) {
362
374
  case couchbase::error::common_errc::unambiguous_timeout:
363
375
  return rb_exc_new_cstr(eUnambiguousTimeout, fmt::format("{}: {}", message, ec.message()).c_str());
364
376
 
@@ -417,7 +429,7 @@ cb_map_error_code(std::error_code ec, const std::string& message)
417
429
  return rb_exc_new_cstr(eIndexExists, fmt::format("{}: {}", message, ec.message()).c_str());
418
430
  }
419
431
  } else if (ec.category() == couchbase::error::detail::get_key_value_category()) {
420
- switch (static_cast<couchbase::error::key_value_errc>(ec.value())) {
432
+ switch (couchbase::error::key_value_errc(ec.value())) {
421
433
  case couchbase::error::key_value_errc::document_not_found:
422
434
  return rb_exc_new_cstr(eDocumentNotFound, fmt::format("{}: {}", message, ec.message()).c_str());
423
435
 
@@ -494,7 +506,7 @@ cb_map_error_code(std::error_code ec, const std::string& message)
494
506
  return rb_exc_new_cstr(eXattrCannotModifyVirtualAttribute, fmt::format("{}: {}", message, ec.message()).c_str());
495
507
  }
496
508
  } else if (ec.category() == couchbase::error::detail::get_query_category()) {
497
- switch (static_cast<couchbase::error::query_errc>(ec.value())) {
509
+ switch (couchbase::error::query_errc(ec.value())) {
498
510
  case couchbase::error::query_errc::planning_failure:
499
511
  return rb_exc_new_cstr(ePlanningFailure, fmt::format("{}: {}", message, ec.message()).c_str());
500
512
 
@@ -505,14 +517,14 @@ cb_map_error_code(std::error_code ec, const std::string& message)
505
517
  return rb_exc_new_cstr(ePreparedStatementFailure, fmt::format("{}: {}", message, ec.message()).c_str());
506
518
  }
507
519
  } else if (ec.category() == couchbase::error::detail::get_search_category()) {
508
- switch (static_cast<couchbase::error::search_errc>(ec.value())) {
520
+ switch (couchbase::error::search_errc(ec.value())) {
509
521
  case couchbase::error::search_errc::index_not_ready:
510
522
  return rb_exc_new_cstr(eIndexNotReady, fmt::format("{}: {}", message, ec.message()).c_str());
511
523
  case couchbase::error::search_errc::consistency_mismatch:
512
524
  return rb_exc_new_cstr(eConsistencyMismatch, fmt::format("{}: {}", message, ec.message()).c_str());
513
525
  }
514
526
  } else if (ec.category() == couchbase::error::detail::get_view_category()) {
515
- switch (static_cast<couchbase::error::view_errc>(ec.value())) {
527
+ switch (couchbase::error::view_errc(ec.value())) {
516
528
  case couchbase::error::view_errc::view_not_found:
517
529
  return rb_exc_new_cstr(eViewNotFound, fmt::format("{}: {}", message, ec.message()).c_str());
518
530
 
@@ -520,7 +532,7 @@ cb_map_error_code(std::error_code ec, const std::string& message)
520
532
  return rb_exc_new_cstr(eDesignDocumentNotFound, fmt::format("{}: {}", message, ec.message()).c_str());
521
533
  }
522
534
  } else if (ec.category() == couchbase::error::detail::get_analytics_category()) {
523
- switch (static_cast<couchbase::error::analytics_errc>(ec.value())) {
535
+ switch (couchbase::error::analytics_errc(ec.value())) {
524
536
  case couchbase::error::analytics_errc::compilation_failure:
525
537
  return rb_exc_new_cstr(eCompilationFailure, fmt::format("{}: {}", message, ec.message()).c_str());
526
538
 
@@ -541,9 +553,12 @@ cb_map_error_code(std::error_code ec, const std::string& message)
541
553
 
542
554
  case couchbase::error::analytics_errc::link_not_found:
543
555
  return rb_exc_new_cstr(eLinkNotFound, fmt::format("{}: {}", message, ec.message()).c_str());
556
+
557
+ case couchbase::error::analytics_errc::link_exists:
558
+ return rb_exc_new_cstr(eLinkExists, fmt::format("{}: {}", message, ec.message()).c_str());
544
559
  }
545
560
  } else if (ec.category() == couchbase::error::detail::get_management_category()) {
546
- switch (static_cast<couchbase::error::management_errc>(ec.value())) {
561
+ switch (couchbase::error::management_errc(ec.value())) {
547
562
  case couchbase::error::management_errc::collection_exists:
548
563
  return rb_exc_new_cstr(eCollectionExists, fmt::format("{}: {}", message, ec.message()).c_str());
549
564
 
@@ -566,7 +581,7 @@ cb_map_error_code(std::error_code ec, const std::string& message)
566
581
  return rb_exc_new_cstr(eBucketNotFlushable, fmt::format("{}: {}", message, ec.message()).c_str());
567
582
  }
568
583
  } else if (ec.category() == couchbase::error::detail::network_error_category()) {
569
- switch (static_cast<couchbase::error::network_errc>(ec.value())) {
584
+ switch (couchbase::error::network_errc(ec.value())) {
570
585
  case couchbase::error::network_errc::resolve_failure:
571
586
  return rb_exc_new_cstr(eResolveFailure, fmt::format("{}: {}", message, ec.message()).c_str());
572
587
 
@@ -836,6 +851,126 @@ cb_wait_for_future(Future&& f) -> decltype(f.get())
836
851
  return std::move(arg.res);
837
852
  }
838
853
 
854
+ template<typename Request>
855
+ [[nodiscard]] VALUE
856
+ cb_extract_timeout(Request& req, VALUE options)
857
+ {
858
+ if (!NIL_P(options)) {
859
+ switch (TYPE(options)) {
860
+ case T_HASH:
861
+ return cb_extract_timeout(req, rb_hash_aref(options, rb_id2sym(rb_intern("timeout"))));
862
+ case T_FIXNUM:
863
+ case T_BIGNUM:
864
+ req.timeout = std::chrono::milliseconds(NUM2ULL(options));
865
+ break;
866
+ default:
867
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("timeout must be an Integer, but given %+" PRIsVALUE, options));
868
+ }
869
+ }
870
+ return Qnil;
871
+ }
872
+
873
+ [[nodiscard]] VALUE
874
+ cb_extract_timeout(std::chrono::milliseconds& timeout, VALUE options)
875
+ {
876
+ if (!NIL_P(options)) {
877
+ switch (TYPE(options)) {
878
+ case T_HASH:
879
+ return cb_extract_timeout(timeout, rb_hash_aref(options, rb_id2sym(rb_intern("timeout"))));
880
+ case T_FIXNUM:
881
+ case T_BIGNUM:
882
+ timeout = std::chrono::milliseconds(NUM2ULL(options));
883
+ break;
884
+ default:
885
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("timeout must be an Integer, but given %+" PRIsVALUE, options));
886
+ }
887
+ }
888
+ return Qnil;
889
+ }
890
+
891
+ [[nodiscard]] VALUE
892
+ cb_extract_option_bool(bool& field, VALUE options, const char* name)
893
+ {
894
+ if (!NIL_P(options) && TYPE(options) == T_HASH) {
895
+ VALUE val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
896
+ if (NIL_P(val)) {
897
+ return Qnil;
898
+ }
899
+ switch (TYPE(val)) {
900
+ case T_TRUE:
901
+ field = true;
902
+ break;
903
+ case T_FALSE:
904
+ field = false;
905
+ break;
906
+ default:
907
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("%s must be a Boolean, but given %+" PRIsVALUE, name, val));
908
+ }
909
+ }
910
+ return Qnil;
911
+ }
912
+
913
+ [[nodiscard]] VALUE
914
+ cb_extract_option_number(std::size_t& field, VALUE options, const char* name)
915
+ {
916
+ if (!NIL_P(options) && TYPE(options) == T_HASH) {
917
+ VALUE val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
918
+ if (NIL_P(val)) {
919
+ return Qnil;
920
+ }
921
+ switch (TYPE(val)) {
922
+ case T_FIXNUM:
923
+ field = FIX2ULONG(val);
924
+ break;
925
+ case T_BIGNUM:
926
+ field = NUM2ULL(val);
927
+ break;
928
+ default:
929
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("%s must be a Integer, but given %+" PRIsVALUE, name, val));
930
+ }
931
+ }
932
+ return Qnil;
933
+ }
934
+
935
+ [[nodiscard]] VALUE
936
+ cb_extract_option_milliseconds(std::chrono::milliseconds& field, VALUE options, const char* name)
937
+ {
938
+ if (!NIL_P(options) && TYPE(options) == T_HASH) {
939
+ VALUE val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
940
+ if (NIL_P(val)) {
941
+ return Qnil;
942
+ }
943
+ switch (TYPE(val)) {
944
+ case T_FIXNUM:
945
+ field = std::chrono::milliseconds(FIX2ULONG(val));
946
+ break;
947
+ case T_BIGNUM:
948
+ field = std::chrono::milliseconds(NUM2ULL(val));
949
+ break;
950
+ default:
951
+ return rb_exc_new_str(rb_eArgError,
952
+ rb_sprintf("%s must be a Integer representing milliseconds, but given %+" PRIsVALUE, name, val));
953
+ }
954
+ }
955
+ return Qnil;
956
+ }
957
+
958
+ [[nodiscard]] VALUE
959
+ cb_extract_option_array(VALUE& val, VALUE options, const char* name)
960
+ {
961
+ if (!NIL_P(options) && TYPE(options) == T_HASH) {
962
+ val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
963
+ if (NIL_P(val)) {
964
+ return Qnil;
965
+ }
966
+ if (TYPE(val) == T_ARRAY) {
967
+ return Qnil;
968
+ }
969
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("%s must be an Array, but given %+" PRIsVALUE, name, val));
970
+ }
971
+ return Qnil;
972
+ }
973
+
839
974
  static VALUE
840
975
  cb_Backend_open(VALUE self, VALUE connection_string, VALUE credentials, VALUE options)
841
976
  {
@@ -880,21 +1015,28 @@ cb_Backend_open(VALUE self, VALUE connection_string, VALUE credentials, VALUE op
880
1015
  if (NIL_P(certificate_path) || NIL_P(key_path)) {
881
1016
  auth.username.assign(RSTRING_PTR(username), static_cast<size_t>(RSTRING_LEN(username)));
882
1017
  auth.password.assign(RSTRING_PTR(password), static_cast<size_t>(RSTRING_LEN(password)));
883
- VALUE allowed_mechanisms = rb_hash_aref(options, rb_id2sym(rb_intern("allowed_sasl_mechanisms")));
884
- if (!NIL_P(allowed_mechanisms)) {
885
- Check_Type(allowed_mechanisms, T_ARRAY);
886
- auto allowed_mechanisms_size = static_cast<size_t>(RARRAY_LEN(allowed_mechanisms));
887
- auth.allowed_sasl_mechanisms.reserve(allowed_mechanisms_size);
888
- for (size_t i = 0; i < allowed_mechanisms_size; ++i) {
889
- VALUE mechanism = rb_ary_entry(allowed_mechanisms, static_cast<long>(i));
890
- if (mechanism == rb_id2sym(rb_intern("scram_sha512"))) {
891
- auth.allowed_sasl_mechanisms.emplace_back("SCRAM-SHA512");
892
- } else if (mechanism == rb_id2sym(rb_intern("scram_sha256"))) {
893
- auth.allowed_sasl_mechanisms.emplace_back("SCRAM-SHA256");
894
- } else if (mechanism == rb_id2sym(rb_intern("scram_sha1"))) {
895
- auth.allowed_sasl_mechanisms.emplace_back("SCRAM-SHA1");
896
- } else if (mechanism == rb_id2sym(rb_intern("plain"))) {
897
- auth.allowed_sasl_mechanisms.emplace_back("PLAIN");
1018
+ if (!NIL_P(options)) {
1019
+ VALUE allowed_mechanisms = rb_hash_aref(options, rb_id2sym(rb_intern("allowed_sasl_mechanisms")));
1020
+ if (!NIL_P(allowed_mechanisms)) {
1021
+ Check_Type(allowed_mechanisms, T_ARRAY);
1022
+ auto allowed_mechanisms_size = static_cast<size_t>(RARRAY_LEN(allowed_mechanisms));
1023
+ if (allowed_mechanisms_size < 1) {
1024
+ exc = rb_exc_new_cstr(eInvalidArgument, "allowed_sasl_mechanisms list cannot be empty");
1025
+ break;
1026
+ }
1027
+ auth.allowed_sasl_mechanisms.clear();
1028
+ auth.allowed_sasl_mechanisms.reserve(allowed_mechanisms_size);
1029
+ for (size_t i = 0; i < allowed_mechanisms_size; ++i) {
1030
+ VALUE mechanism = rb_ary_entry(allowed_mechanisms, static_cast<long>(i));
1031
+ if (mechanism == rb_id2sym(rb_intern("scram_sha512"))) {
1032
+ auth.allowed_sasl_mechanisms.emplace_back("SCRAM-SHA512");
1033
+ } else if (mechanism == rb_id2sym(rb_intern("scram_sha256"))) {
1034
+ auth.allowed_sasl_mechanisms.emplace_back("SCRAM-SHA256");
1035
+ } else if (mechanism == rb_id2sym(rb_intern("scram_sha1"))) {
1036
+ auth.allowed_sasl_mechanisms.emplace_back("SCRAM-SHA1");
1037
+ } else if (mechanism == rb_id2sym(rb_intern("plain"))) {
1038
+ auth.allowed_sasl_mechanisms.emplace_back("PLAIN");
1039
+ }
898
1040
  }
899
1041
  }
900
1042
  }
@@ -909,6 +1051,66 @@ cb_Backend_open(VALUE self, VALUE connection_string, VALUE credentials, VALUE op
909
1051
  auth.key_path.assign(RSTRING_PTR(key_path), static_cast<size_t>(RSTRING_LEN(key_path)));
910
1052
  }
911
1053
  couchbase::origin origin(auth, connstr);
1054
+ exc = cb_extract_option_bool(origin.options().enable_tracing, options, "enable_tracing");
1055
+ if (!NIL_P(exc)) {
1056
+ break;
1057
+ }
1058
+ if (origin.options().enable_tracing) {
1059
+ exc =
1060
+ cb_extract_option_milliseconds(origin.options().tracing_options.orphaned_emit_interval, options, "orphaned_emit_interval");
1061
+ if (!NIL_P(exc)) {
1062
+ break;
1063
+ }
1064
+ exc = cb_extract_option_number(origin.options().tracing_options.orphaned_sample_size, options, "orphaned_sample_size");
1065
+ if (!NIL_P(exc)) {
1066
+ break;
1067
+ }
1068
+
1069
+ exc =
1070
+ cb_extract_option_milliseconds(origin.options().tracing_options.threshold_emit_interval, options, "threshold_emit_interval");
1071
+ if (!NIL_P(exc)) {
1072
+ break;
1073
+ }
1074
+ exc = cb_extract_option_number(origin.options().tracing_options.threshold_sample_size, options, "threshold_sample_size");
1075
+ if (!NIL_P(exc)) {
1076
+ break;
1077
+ }
1078
+ exc = cb_extract_option_milliseconds(origin.options().tracing_options.key_value_threshold, options, "key_value_threshold");
1079
+ if (!NIL_P(exc)) {
1080
+ break;
1081
+ }
1082
+ exc = cb_extract_option_milliseconds(origin.options().tracing_options.query_threshold, options, "query_threshold");
1083
+ if (!NIL_P(exc)) {
1084
+ break;
1085
+ }
1086
+ exc = cb_extract_option_milliseconds(origin.options().tracing_options.view_threshold, options, "view_threshold");
1087
+ if (!NIL_P(exc)) {
1088
+ break;
1089
+ }
1090
+ exc = cb_extract_option_milliseconds(origin.options().tracing_options.search_threshold, options, "search_threshold");
1091
+ if (!NIL_P(exc)) {
1092
+ break;
1093
+ }
1094
+ exc = cb_extract_option_milliseconds(origin.options().tracing_options.analytics_threshold, options, "analytics_threshold");
1095
+ if (!NIL_P(exc)) {
1096
+ break;
1097
+ }
1098
+ exc = cb_extract_option_milliseconds(origin.options().tracing_options.management_threshold, options, "management_threshold");
1099
+ if (!NIL_P(exc)) {
1100
+ break;
1101
+ }
1102
+ }
1103
+ exc = cb_extract_option_bool(origin.options().enable_metrics, options, "enable_metrics");
1104
+ if (!NIL_P(exc)) {
1105
+ break;
1106
+ }
1107
+ if (origin.options().enable_metrics) {
1108
+ exc = cb_extract_option_milliseconds(origin.options().metrics_options.emit_interval, options, "metrics_emit_interval");
1109
+ if (!NIL_P(exc)) {
1110
+ break;
1111
+ }
1112
+ }
1113
+
912
1114
  auto barrier = std::make_shared<std::promise<std::error_code>>();
913
1115
  auto f = barrier->get_future();
914
1116
  backend->cluster->open(origin, [barrier](std::error_code ec) mutable { barrier->set_value(ec); });
@@ -966,7 +1168,7 @@ cb_Backend_diagnostics(VALUE self, VALUE report_id)
966
1168
  for (const auto& svcs : resp.services) {
967
1169
  VALUE type = Qnil;
968
1170
  switch (svcs.first) {
969
- case couchbase::service_type::kv:
1171
+ case couchbase::service_type::key_value:
970
1172
  type = rb_id2sym(rb_intern("kv"));
971
1173
  break;
972
1174
  case couchbase::service_type::query:
@@ -978,7 +1180,7 @@ cb_Backend_diagnostics(VALUE self, VALUE report_id)
978
1180
  case couchbase::service_type::search:
979
1181
  type = rb_id2sym(rb_intern("search"));
980
1182
  break;
981
- case couchbase::service_type::views:
1183
+ case couchbase::service_type::view:
982
1184
  type = rb_id2sym(rb_intern("views"));
983
1185
  break;
984
1186
  case couchbase::service_type::management:
@@ -1059,81 +1261,6 @@ cb_Backend_open_bucket(VALUE self, VALUE bucket, VALUE wait_until_ready)
1059
1261
  return Qnil;
1060
1262
  }
1061
1263
 
1062
- template<typename Request>
1063
- [[nodiscard]] VALUE
1064
- cb_extract_timeout(Request& req, VALUE options)
1065
- {
1066
- if (!NIL_P(options)) {
1067
- switch (TYPE(options)) {
1068
- case T_HASH:
1069
- return cb_extract_timeout(req, rb_hash_aref(options, rb_id2sym(rb_intern("timeout"))));
1070
- case T_FIXNUM:
1071
- case T_BIGNUM:
1072
- req.timeout = std::chrono::milliseconds(NUM2ULL(options));
1073
- break;
1074
- default:
1075
- return rb_exc_new_str(rb_eArgError, rb_sprintf("timeout must be an Integer, but given %+" PRIsVALUE, options));
1076
- }
1077
- }
1078
- return Qnil;
1079
- }
1080
-
1081
- [[nodiscard]] VALUE
1082
- cb_extract_timeout(std::chrono::milliseconds& timeout, VALUE options)
1083
- {
1084
- if (!NIL_P(options)) {
1085
- switch (TYPE(options)) {
1086
- case T_HASH:
1087
- return cb_extract_timeout(timeout, rb_hash_aref(options, rb_id2sym(rb_intern("timeout"))));
1088
- case T_FIXNUM:
1089
- case T_BIGNUM:
1090
- timeout = std::chrono::milliseconds(NUM2ULL(options));
1091
- break;
1092
- default:
1093
- return rb_exc_new_str(rb_eArgError, rb_sprintf("timeout must be an Integer, but given %+" PRIsVALUE, options));
1094
- }
1095
- }
1096
- return Qnil;
1097
- }
1098
-
1099
- [[nodiscard]] VALUE
1100
- cb_extract_option_bool(bool& field, VALUE options, const char* name)
1101
- {
1102
- if (!NIL_P(options) && TYPE(options) == T_HASH) {
1103
- VALUE val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
1104
- if (NIL_P(val)) {
1105
- return Qnil;
1106
- }
1107
- switch (TYPE(val)) {
1108
- case T_TRUE:
1109
- field = true;
1110
- break;
1111
- case T_FALSE:
1112
- field = false;
1113
- break;
1114
- default:
1115
- return rb_exc_new_str(rb_eArgError, rb_sprintf("%s must be a Boolean, but given %+" PRIsVALUE, name, val));
1116
- }
1117
- }
1118
- return Qnil;
1119
- }
1120
-
1121
- [[nodiscard]] VALUE
1122
- cb_extract_option_array(VALUE& val, VALUE options, const char* name)
1123
- {
1124
- if (!NIL_P(options) && TYPE(options) == T_HASH) {
1125
- val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
1126
- if (NIL_P(val)) {
1127
- return Qnil;
1128
- }
1129
- if (TYPE(val) == T_ARRAY) {
1130
- return Qnil;
1131
- }
1132
- return rb_exc_new_str(rb_eArgError, rb_sprintf("%s must be an Array, but given %+" PRIsVALUE, name, val));
1133
- }
1134
- return Qnil;
1135
- }
1136
-
1137
1264
  [[nodiscard]] VALUE
1138
1265
  cb_extract_array_of_ids(std::vector<couchbase::document_id>& ids, VALUE arg)
1139
1266
  {
@@ -1189,7 +1316,7 @@ cb_extract_array_of_id_content(std::vector<std::tuple<couchbase::document_id, st
1189
1316
  if (TYPE(entry) != T_ARRAY || RARRAY_LEN(entry) != 5) {
1190
1317
  return rb_exc_new_str(
1191
1318
  rb_eArgError,
1192
- rb_sprintf("ID/content tuple must be represented as an Array[bucket, collection, id, content], but given %+" PRIsVALUE,
1319
+ rb_sprintf("ID/content tuple must be represented as an Array[bucket, collection, id, content, flags], but given %+" PRIsVALUE,
1193
1320
  entry));
1194
1321
  }
1195
1322
  VALUE bucket = rb_ary_entry(entry, 0);
@@ -1268,13 +1395,12 @@ cb_extract_array_of_id_cas(std::vector<std::pair<couchbase::document_id, std::ui
1268
1395
  }
1269
1396
  }
1270
1397
 
1271
- id_cas.emplace_back(std::make_pair(
1272
- couchbase::document_id{
1273
- std::string(RSTRING_PTR(bucket), static_cast<size_t>(RSTRING_LEN(bucket))),
1274
- std::string(RSTRING_PTR(collection), static_cast<size_t>(RSTRING_LEN(collection))),
1275
- std::string(RSTRING_PTR(id), static_cast<size_t>(RSTRING_LEN(id))),
1276
- },
1277
- cas_val));
1398
+ id_cas.emplace_back(std::pair{ couchbase::document_id{
1399
+ std::string(RSTRING_PTR(bucket), static_cast<size_t>(RSTRING_LEN(bucket))),
1400
+ std::string(RSTRING_PTR(collection), static_cast<size_t>(RSTRING_LEN(collection))),
1401
+ std::string(RSTRING_PTR(id), static_cast<size_t>(RSTRING_LEN(id))),
1402
+ },
1403
+ cas_val });
1278
1404
  }
1279
1405
 
1280
1406
  return Qnil;
@@ -1313,37 +1439,71 @@ cb_extract_option_string(VALUE& val, VALUE options, const char* name)
1313
1439
  }
1314
1440
 
1315
1441
  [[nodiscard]] VALUE
1316
- cb_extract_option_fixnum(VALUE& val, VALUE options, const char* name)
1442
+ cb_extract_option_string(std::string& target, VALUE options, const char* name)
1317
1443
  {
1318
1444
  if (!NIL_P(options) && TYPE(options) == T_HASH) {
1319
- val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
1445
+ VALUE val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
1320
1446
  if (NIL_P(val)) {
1321
1447
  return Qnil;
1322
1448
  }
1323
- if (TYPE(val) == T_FIXNUM) {
1449
+ if (TYPE(val) == T_STRING) {
1450
+ target.assign(RSTRING_PTR(val), static_cast<size_t>(RSTRING_LEN(val)));
1324
1451
  return Qnil;
1325
1452
  }
1326
- return rb_exc_new_str(rb_eArgError, rb_sprintf("%s must be an Integer, but given %+" PRIsVALUE, name, val));
1453
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("%s must be an String, but given %+" PRIsVALUE, name, val));
1327
1454
  }
1328
1455
  return Qnil;
1329
1456
  }
1330
1457
 
1331
1458
  [[nodiscard]] VALUE
1332
- cb_extract_option_bignum(VALUE& val, VALUE options, const char* name)
1459
+ cb_extract_option_string(std::optional<std::string>& target, VALUE options, const char* name)
1333
1460
  {
1334
1461
  if (!NIL_P(options) && TYPE(options) == T_HASH) {
1335
- val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
1462
+ VALUE val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
1336
1463
  if (NIL_P(val)) {
1337
1464
  return Qnil;
1338
1465
  }
1339
- switch (TYPE(val)) {
1340
- case T_FIXNUM:
1341
- case T_BIGNUM:
1342
- return Qnil;
1343
- default:
1344
- break;
1466
+ if (TYPE(val) == T_STRING) {
1467
+ target.emplace(std::string(RSTRING_PTR(val), static_cast<size_t>(RSTRING_LEN(val))));
1468
+ return Qnil;
1345
1469
  }
1346
- return rb_exc_new_str(rb_eArgError, rb_sprintf("%s must be an Integer, but given %+" PRIsVALUE, name, val));
1470
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("%s must be an String, but given %+" PRIsVALUE, name, val));
1471
+ }
1472
+ return Qnil;
1473
+ }
1474
+
1475
+ [[nodiscard]] VALUE
1476
+ cb_extract_option_fixnum(VALUE& val, VALUE options, const char* name)
1477
+ {
1478
+ if (!NIL_P(options) && TYPE(options) == T_HASH) {
1479
+ val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
1480
+ if (NIL_P(val)) {
1481
+ return Qnil;
1482
+ }
1483
+ if (TYPE(val) == T_FIXNUM) {
1484
+ return Qnil;
1485
+ }
1486
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("%s must be an Integer, but given %+" PRIsVALUE, name, val));
1487
+ }
1488
+ return Qnil;
1489
+ }
1490
+
1491
+ [[nodiscard]] VALUE
1492
+ cb_extract_option_bignum(VALUE& val, VALUE options, const char* name)
1493
+ {
1494
+ if (!NIL_P(options) && TYPE(options) == T_HASH) {
1495
+ val = rb_hash_aref(options, rb_id2sym(rb_intern(name)));
1496
+ if (NIL_P(val)) {
1497
+ return Qnil;
1498
+ }
1499
+ switch (TYPE(val)) {
1500
+ case T_FIXNUM:
1501
+ case T_BIGNUM:
1502
+ return Qnil;
1503
+ default:
1504
+ break;
1505
+ }
1506
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("%s must be an Integer, but given %+" PRIsVALUE, name, val));
1347
1507
  }
1348
1508
  return Qnil;
1349
1509
  }
@@ -1432,7 +1592,7 @@ cb_Backend_ping(VALUE self, VALUE bucket, VALUE options)
1432
1592
  for (size_t i = 0; i < entries_num; ++i) {
1433
1593
  VALUE entry = rb_ary_entry(services, static_cast<long>(i));
1434
1594
  if (entry == rb_id2sym(rb_intern("kv"))) {
1435
- selected_services.insert(couchbase::service_type::kv);
1595
+ selected_services.insert(couchbase::service_type::key_value);
1436
1596
  } else if (entry == rb_id2sym(rb_intern("query"))) {
1437
1597
  selected_services.insert(couchbase::service_type::query);
1438
1598
  } else if (entry == rb_id2sym(rb_intern("analytics"))) {
@@ -1440,7 +1600,7 @@ cb_Backend_ping(VALUE self, VALUE bucket, VALUE options)
1440
1600
  } else if (entry == rb_id2sym(rb_intern("search"))) {
1441
1601
  selected_services.insert(couchbase::service_type::search);
1442
1602
  } else if (entry == rb_id2sym(rb_intern("views"))) {
1443
- selected_services.insert(couchbase::service_type::views);
1603
+ selected_services.insert(couchbase::service_type::view);
1444
1604
  }
1445
1605
  }
1446
1606
  }
@@ -1459,7 +1619,7 @@ cb_Backend_ping(VALUE self, VALUE bucket, VALUE options)
1459
1619
  for (const auto& svcs : resp.services) {
1460
1620
  VALUE type = Qnil;
1461
1621
  switch (svcs.first) {
1462
- case couchbase::service_type::kv:
1622
+ case couchbase::service_type::key_value:
1463
1623
  type = rb_id2sym(rb_intern("kv"));
1464
1624
  break;
1465
1625
  case couchbase::service_type::query:
@@ -1471,7 +1631,7 @@ cb_Backend_ping(VALUE self, VALUE bucket, VALUE options)
1471
1631
  case couchbase::service_type::search:
1472
1632
  type = rb_id2sym(rb_intern("search"));
1473
1633
  break;
1474
- case couchbase::service_type::views:
1634
+ case couchbase::service_type::view:
1475
1635
  type = rb_id2sym(rb_intern("views"));
1476
1636
  break;
1477
1637
  case couchbase::service_type::management:
@@ -3516,7 +3676,7 @@ cb_generate_bucket_settings(VALUE bucket, couchbase::operations::bucket_settings
3516
3676
  }
3517
3677
 
3518
3678
  static VALUE
3519
- cb_Backend_bucket_create(VALUE self, VALUE bucket_settings, VALUE timeout)
3679
+ cb_Backend_bucket_create(VALUE self, VALUE bucket_settings, VALUE options)
3520
3680
  {
3521
3681
  cb_backend_data* backend = nullptr;
3522
3682
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -3527,11 +3687,14 @@ cb_Backend_bucket_create(VALUE self, VALUE bucket_settings, VALUE timeout)
3527
3687
  }
3528
3688
 
3529
3689
  Check_Type(bucket_settings, T_HASH);
3690
+ if (!NIL_P(options)) {
3691
+ Check_Type(options, T_HASH);
3692
+ }
3530
3693
 
3531
3694
  VALUE exc = Qnil;
3532
3695
  do {
3533
3696
  couchbase::operations::bucket_create_request req{};
3534
- exc = cb_extract_timeout(req, timeout);
3697
+ exc = cb_extract_timeout(req, options);
3535
3698
  if (!NIL_P(exc)) {
3536
3699
  break;
3537
3700
  }
@@ -3557,7 +3720,7 @@ cb_Backend_bucket_create(VALUE self, VALUE bucket_settings, VALUE timeout)
3557
3720
  }
3558
3721
 
3559
3722
  static VALUE
3560
- cb_Backend_bucket_update(VALUE self, VALUE bucket_settings, VALUE timeout)
3723
+ cb_Backend_bucket_update(VALUE self, VALUE bucket_settings, VALUE options)
3561
3724
  {
3562
3725
  cb_backend_data* backend = nullptr;
3563
3726
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -3568,10 +3731,13 @@ cb_Backend_bucket_update(VALUE self, VALUE bucket_settings, VALUE timeout)
3568
3731
  }
3569
3732
 
3570
3733
  Check_Type(bucket_settings, T_HASH);
3734
+ if (!NIL_P(options)) {
3735
+ Check_Type(options, T_HASH);
3736
+ }
3571
3737
  VALUE exc = Qnil;
3572
3738
  do {
3573
3739
  couchbase::operations::bucket_update_request req{};
3574
- exc = cb_extract_timeout(req, timeout);
3740
+ exc = cb_extract_timeout(req, options);
3575
3741
  if (!NIL_P(exc)) {
3576
3742
  break;
3577
3743
  }
@@ -3596,7 +3762,7 @@ cb_Backend_bucket_update(VALUE self, VALUE bucket_settings, VALUE timeout)
3596
3762
  }
3597
3763
 
3598
3764
  static VALUE
3599
- cb_Backend_bucket_drop(VALUE self, VALUE bucket_name, VALUE timeout)
3765
+ cb_Backend_bucket_drop(VALUE self, VALUE bucket_name, VALUE options)
3600
3766
  {
3601
3767
  cb_backend_data* backend = nullptr;
3602
3768
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -3607,11 +3773,14 @@ cb_Backend_bucket_drop(VALUE self, VALUE bucket_name, VALUE timeout)
3607
3773
  }
3608
3774
 
3609
3775
  Check_Type(bucket_name, T_STRING);
3776
+ if (!NIL_P(options)) {
3777
+ Check_Type(options, T_HASH);
3778
+ }
3610
3779
 
3611
3780
  VALUE exc = Qnil;
3612
3781
  do {
3613
3782
  couchbase::operations::bucket_drop_request req{};
3614
- exc = cb_extract_timeout(req, timeout);
3783
+ exc = cb_extract_timeout(req, options);
3615
3784
  if (!NIL_P(exc)) {
3616
3785
  break;
3617
3786
  }
@@ -3632,7 +3801,7 @@ cb_Backend_bucket_drop(VALUE self, VALUE bucket_name, VALUE timeout)
3632
3801
  }
3633
3802
 
3634
3803
  static VALUE
3635
- cb_Backend_bucket_flush(VALUE self, VALUE bucket_name, VALUE timeout)
3804
+ cb_Backend_bucket_flush(VALUE self, VALUE bucket_name, VALUE options)
3636
3805
  {
3637
3806
  cb_backend_data* backend = nullptr;
3638
3807
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -3643,11 +3812,14 @@ cb_Backend_bucket_flush(VALUE self, VALUE bucket_name, VALUE timeout)
3643
3812
  }
3644
3813
 
3645
3814
  Check_Type(bucket_name, T_STRING);
3815
+ if (!NIL_P(options)) {
3816
+ Check_Type(options, T_HASH);
3817
+ }
3646
3818
 
3647
3819
  VALUE exc = Qnil;
3648
3820
  do {
3649
3821
  couchbase::operations::bucket_flush_request req{};
3650
- exc = cb_extract_timeout(req, timeout);
3822
+ exc = cb_extract_timeout(req, options);
3651
3823
  if (!NIL_P(exc)) {
3652
3824
  break;
3653
3825
  }
@@ -3768,7 +3940,7 @@ cb_extract_bucket_settings(const couchbase::operations::bucket_settings& entry,
3768
3940
  }
3769
3941
 
3770
3942
  static VALUE
3771
- cb_Backend_bucket_get_all(VALUE self, VALUE timeout)
3943
+ cb_Backend_bucket_get_all(VALUE self, VALUE options)
3772
3944
  {
3773
3945
  cb_backend_data* backend = nullptr;
3774
3946
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -3778,10 +3950,14 @@ cb_Backend_bucket_get_all(VALUE self, VALUE timeout)
3778
3950
  return Qnil;
3779
3951
  }
3780
3952
 
3953
+ if (!NIL_P(options)) {
3954
+ Check_Type(options, T_HASH);
3955
+ }
3956
+
3781
3957
  VALUE exc = Qnil;
3782
3958
  do {
3783
3959
  couchbase::operations::bucket_get_all_request req{};
3784
- exc = cb_extract_timeout(req, timeout);
3960
+ exc = cb_extract_timeout(req, options);
3785
3961
  if (!NIL_P(exc)) {
3786
3962
  break;
3787
3963
  }
@@ -3809,7 +3985,7 @@ cb_Backend_bucket_get_all(VALUE self, VALUE timeout)
3809
3985
  }
3810
3986
 
3811
3987
  static VALUE
3812
- cb_Backend_bucket_get(VALUE self, VALUE bucket_name, VALUE timeout)
3988
+ cb_Backend_bucket_get(VALUE self, VALUE bucket_name, VALUE options)
3813
3989
  {
3814
3990
  cb_backend_data* backend = nullptr;
3815
3991
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -3820,11 +3996,14 @@ cb_Backend_bucket_get(VALUE self, VALUE bucket_name, VALUE timeout)
3820
3996
  }
3821
3997
 
3822
3998
  Check_Type(bucket_name, T_STRING);
3999
+ if (!NIL_P(options)) {
4000
+ Check_Type(options, T_HASH);
4001
+ }
3823
4002
 
3824
4003
  VALUE exc = Qnil;
3825
4004
  do {
3826
4005
  couchbase::operations::bucket_get_request req{};
3827
- exc = cb_extract_timeout(req, timeout);
4006
+ exc = cb_extract_timeout(req, options);
3828
4007
  if (!NIL_P(exc)) {
3829
4008
  break;
3830
4009
  }
@@ -4475,7 +4654,7 @@ cb_Backend_cluster_enable_developer_preview(VALUE self)
4475
4654
  }
4476
4655
 
4477
4656
  static VALUE
4478
- cb_Backend_scope_get_all(VALUE self, VALUE bucket_name, VALUE timeout)
4657
+ cb_Backend_scope_get_all(VALUE self, VALUE bucket_name, VALUE options)
4479
4658
  {
4480
4659
  cb_backend_data* backend = nullptr;
4481
4660
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -4486,11 +4665,14 @@ cb_Backend_scope_get_all(VALUE self, VALUE bucket_name, VALUE timeout)
4486
4665
  }
4487
4666
 
4488
4667
  Check_Type(bucket_name, T_STRING);
4668
+ if (!NIL_P(options)) {
4669
+ Check_Type(options, T_HASH);
4670
+ }
4489
4671
 
4490
4672
  VALUE exc = Qnil;
4491
4673
  do {
4492
4674
  couchbase::operations::scope_get_all_request req{};
4493
- exc = cb_extract_timeout(req, timeout);
4675
+ exc = cb_extract_timeout(req, options);
4494
4676
  if (!NIL_P(exc)) {
4495
4677
  break;
4496
4678
  }
@@ -4587,7 +4769,7 @@ cb_Backend_collections_manifest_get(VALUE self, VALUE bucket_name, VALUE timeout
4587
4769
  }
4588
4770
 
4589
4771
  static VALUE
4590
- cb_Backend_scope_create(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE timeout)
4772
+ cb_Backend_scope_create(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE options)
4591
4773
  {
4592
4774
  cb_backend_data* backend = nullptr;
4593
4775
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -4599,11 +4781,14 @@ cb_Backend_scope_create(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE t
4599
4781
 
4600
4782
  Check_Type(bucket_name, T_STRING);
4601
4783
  Check_Type(scope_name, T_STRING);
4784
+ if (!NIL_P(options)) {
4785
+ Check_Type(options, T_HASH);
4786
+ }
4602
4787
 
4603
4788
  VALUE exc = Qnil;
4604
4789
  do {
4605
4790
  couchbase::operations::scope_create_request req{};
4606
- exc = cb_extract_timeout(req, timeout);
4791
+ exc = cb_extract_timeout(req, options);
4607
4792
  if (!NIL_P(exc)) {
4608
4793
  break;
4609
4794
  }
@@ -4626,7 +4811,7 @@ cb_Backend_scope_create(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE t
4626
4811
  }
4627
4812
 
4628
4813
  static VALUE
4629
- cb_Backend_scope_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE timeout)
4814
+ cb_Backend_scope_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE options)
4630
4815
  {
4631
4816
  cb_backend_data* backend = nullptr;
4632
4817
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -4638,11 +4823,14 @@ cb_Backend_scope_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE tim
4638
4823
 
4639
4824
  Check_Type(bucket_name, T_STRING);
4640
4825
  Check_Type(scope_name, T_STRING);
4826
+ if (!NIL_P(options)) {
4827
+ Check_Type(options, T_HASH);
4828
+ }
4641
4829
 
4642
4830
  VALUE exc = Qnil;
4643
4831
  do {
4644
4832
  couchbase::operations::scope_drop_request req{};
4645
- exc = cb_extract_timeout(req, timeout);
4833
+ exc = cb_extract_timeout(req, options);
4646
4834
  if (!NIL_P(exc)) {
4647
4835
  break;
4648
4836
  }
@@ -4665,7 +4853,7 @@ cb_Backend_scope_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE tim
4665
4853
  }
4666
4854
 
4667
4855
  static VALUE
4668
- cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE max_expiry, VALUE timeout)
4856
+ cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE max_expiry, VALUE options)
4669
4857
  {
4670
4858
  cb_backend_data* backend = nullptr;
4671
4859
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -4678,11 +4866,14 @@ cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VA
4678
4866
  Check_Type(bucket_name, T_STRING);
4679
4867
  Check_Type(scope_name, T_STRING);
4680
4868
  Check_Type(collection_name, T_STRING);
4869
+ if (!NIL_P(options)) {
4870
+ Check_Type(options, T_HASH);
4871
+ }
4681
4872
 
4682
4873
  VALUE exc = Qnil;
4683
4874
  do {
4684
4875
  couchbase::operations::collection_create_request req{};
4685
- exc = cb_extract_timeout(req, timeout);
4876
+ exc = cb_extract_timeout(req, options);
4686
4877
  if (!NIL_P(exc)) {
4687
4878
  break;
4688
4879
  }
@@ -4713,7 +4904,7 @@ cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VA
4713
4904
  }
4714
4905
 
4715
4906
  static VALUE
4716
- cb_Backend_collection_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE timeout)
4907
+ cb_Backend_collection_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE options)
4717
4908
  {
4718
4909
  cb_backend_data* backend = nullptr;
4719
4910
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -4726,11 +4917,14 @@ cb_Backend_collection_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALU
4726
4917
  Check_Type(bucket_name, T_STRING);
4727
4918
  Check_Type(scope_name, T_STRING);
4728
4919
  Check_Type(collection_name, T_STRING);
4920
+ if (!NIL_P(options)) {
4921
+ Check_Type(options, T_HASH);
4922
+ }
4729
4923
 
4730
4924
  VALUE exc = Qnil;
4731
4925
  do {
4732
4926
  couchbase::operations::collection_drop_request req{};
4733
- exc = cb_extract_timeout(req, timeout);
4927
+ exc = cb_extract_timeout(req, options);
4734
4928
  if (!NIL_P(exc)) {
4735
4929
  break;
4736
4930
  }
@@ -4757,7 +4951,7 @@ cb_Backend_collection_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALU
4757
4951
  }
4758
4952
 
4759
4953
  static VALUE
4760
- cb_Backend_query_index_get_all(VALUE self, VALUE bucket_name, VALUE timeout)
4954
+ cb_Backend_query_index_get_all(VALUE self, VALUE bucket_name, VALUE options)
4761
4955
  {
4762
4956
  cb_backend_data* backend = nullptr;
4763
4957
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -4768,11 +4962,14 @@ cb_Backend_query_index_get_all(VALUE self, VALUE bucket_name, VALUE timeout)
4768
4962
  }
4769
4963
 
4770
4964
  Check_Type(bucket_name, T_STRING);
4965
+ if (!NIL_P(options)) {
4966
+ Check_Type(options, T_HASH);
4967
+ }
4771
4968
 
4772
4969
  VALUE exc = Qnil;
4773
4970
  do {
4774
4971
  couchbase::operations::query_index_get_all_request req{};
4775
- exc = cb_extract_timeout(req, timeout);
4972
+ exc = cb_extract_timeout(req, options);
4776
4973
  if (!NIL_P(exc)) {
4777
4974
  break;
4778
4975
  }
@@ -4814,6 +5011,9 @@ cb_Backend_query_index_get_all(VALUE self, VALUE bucket_name, VALUE timeout)
4814
5011
  if (idx.condition) {
4815
5012
  rb_hash_aset(index, rb_id2sym(rb_intern("condition")), cb_str_new(idx.condition.value()));
4816
5013
  }
5014
+ if (idx.partition) {
5015
+ rb_hash_aset(index, rb_id2sym(rb_intern("partition")), cb_str_new(idx.partition.value()));
5016
+ }
4817
5017
  rb_ary_push(indexes, index);
4818
5018
  }
4819
5019
 
@@ -4826,7 +5026,7 @@ cb_Backend_query_index_get_all(VALUE self, VALUE bucket_name, VALUE timeout)
4826
5026
  }
4827
5027
 
4828
5028
  static VALUE
4829
- cb_Backend_query_index_create(VALUE self, VALUE bucket_name, VALUE index_name, VALUE fields, VALUE options, VALUE timeout)
5029
+ cb_Backend_query_index_create(VALUE self, VALUE bucket_name, VALUE index_name, VALUE fields, VALUE options)
4830
5030
  {
4831
5031
  cb_backend_data* backend = nullptr;
4832
5032
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -4839,11 +5039,14 @@ cb_Backend_query_index_create(VALUE self, VALUE bucket_name, VALUE index_name, V
4839
5039
  Check_Type(bucket_name, T_STRING);
4840
5040
  Check_Type(index_name, T_STRING);
4841
5041
  Check_Type(fields, T_ARRAY);
5042
+ if (!NIL_P(options)) {
5043
+ Check_Type(options, T_HASH);
5044
+ }
4842
5045
 
4843
5046
  VALUE exc = Qnil;
4844
5047
  do {
4845
5048
  couchbase::operations::query_index_create_request req{};
4846
- exc = cb_extract_timeout(req, timeout);
5049
+ exc = cb_extract_timeout(req, options);
4847
5050
  if (!NIL_P(exc)) {
4848
5051
  break;
4849
5052
  }
@@ -4857,7 +5060,6 @@ cb_Backend_query_index_create(VALUE self, VALUE bucket_name, VALUE index_name, V
4857
5060
  req.fields.emplace_back(RSTRING_PTR(entry), static_cast<std::size_t>(RSTRING_LEN(entry)));
4858
5061
  }
4859
5062
  if (!NIL_P(options)) {
4860
- Check_Type(options, T_HASH);
4861
5063
  VALUE ignore_if_exists = rb_hash_aref(options, rb_id2sym(rb_intern("ignore_if_exists")));
4862
5064
  if (ignore_if_exists == Qtrue) {
4863
5065
  req.ignore_if_exists = true;
@@ -4927,7 +5129,7 @@ cb_Backend_query_index_create(VALUE self, VALUE bucket_name, VALUE index_name, V
4927
5129
  }
4928
5130
 
4929
5131
  static VALUE
4930
- cb_Backend_query_index_drop(VALUE self, VALUE bucket_name, VALUE index_name, VALUE options, VALUE timeout)
5132
+ cb_Backend_query_index_drop(VALUE self, VALUE bucket_name, VALUE index_name, VALUE options)
4931
5133
  {
4932
5134
  cb_backend_data* backend = nullptr;
4933
5135
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -4939,18 +5141,20 @@ cb_Backend_query_index_drop(VALUE self, VALUE bucket_name, VALUE index_name, VAL
4939
5141
 
4940
5142
  Check_Type(bucket_name, T_STRING);
4941
5143
  Check_Type(index_name, T_STRING);
5144
+ if (!NIL_P(options)) {
5145
+ Check_Type(options, T_HASH);
5146
+ }
4942
5147
 
4943
5148
  VALUE exc = Qnil;
4944
5149
  do {
4945
5150
  couchbase::operations::query_index_drop_request req{};
4946
- exc = cb_extract_timeout(req, timeout);
5151
+ exc = cb_extract_timeout(req, options);
4947
5152
  if (!NIL_P(exc)) {
4948
5153
  break;
4949
5154
  }
4950
5155
  req.bucket_name.assign(RSTRING_PTR(bucket_name), static_cast<size_t>(RSTRING_LEN(bucket_name)));
4951
5156
  req.index_name.assign(RSTRING_PTR(index_name), static_cast<size_t>(RSTRING_LEN(index_name)));
4952
5157
  if (!NIL_P(options)) {
4953
- Check_Type(options, T_HASH);
4954
5158
  VALUE ignore_if_does_not_exist = rb_hash_aref(options, rb_id2sym(rb_intern("ignore_if_does_not_exist")));
4955
5159
  if (ignore_if_does_not_exist == Qtrue) {
4956
5160
  req.ignore_if_does_not_exist = true;
@@ -5006,7 +5210,7 @@ cb_Backend_query_index_drop(VALUE self, VALUE bucket_name, VALUE index_name, VAL
5006
5210
  }
5007
5211
 
5008
5212
  static VALUE
5009
- cb_Backend_query_index_create_primary(VALUE self, VALUE bucket_name, VALUE options, VALUE timeout)
5213
+ cb_Backend_query_index_create_primary(VALUE self, VALUE bucket_name, VALUE options)
5010
5214
  {
5011
5215
  cb_backend_data* backend = nullptr;
5012
5216
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -5024,14 +5228,13 @@ cb_Backend_query_index_create_primary(VALUE self, VALUE bucket_name, VALUE optio
5024
5228
  VALUE exc = Qnil;
5025
5229
  do {
5026
5230
  couchbase::operations::query_index_create_request req{};
5027
- exc = cb_extract_timeout(req, timeout);
5231
+ exc = cb_extract_timeout(req, options);
5028
5232
  if (!NIL_P(exc)) {
5029
5233
  break;
5030
5234
  }
5031
5235
  req.is_primary = true;
5032
5236
  req.bucket_name.assign(RSTRING_PTR(bucket_name), static_cast<size_t>(RSTRING_LEN(bucket_name)));
5033
5237
  if (!NIL_P(options)) {
5034
- Check_Type(options, T_HASH);
5035
5238
  VALUE ignore_if_exists = rb_hash_aref(options, rb_id2sym(rb_intern("ignore_if_exists")));
5036
5239
  if (ignore_if_exists == Qtrue) {
5037
5240
  req.ignore_if_exists = true;
@@ -5100,7 +5303,7 @@ cb_Backend_query_index_create_primary(VALUE self, VALUE bucket_name, VALUE optio
5100
5303
  }
5101
5304
 
5102
5305
  static VALUE
5103
- cb_Backend_query_index_drop_primary(VALUE self, VALUE bucket_name, VALUE options, VALUE timeout)
5306
+ cb_Backend_query_index_drop_primary(VALUE self, VALUE bucket_name, VALUE options)
5104
5307
  {
5105
5308
  cb_backend_data* backend = nullptr;
5106
5309
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -5111,18 +5314,20 @@ cb_Backend_query_index_drop_primary(VALUE self, VALUE bucket_name, VALUE options
5111
5314
  }
5112
5315
 
5113
5316
  Check_Type(bucket_name, T_STRING);
5317
+ if (!NIL_P(options)) {
5318
+ Check_Type(options, T_HASH);
5319
+ }
5114
5320
 
5115
5321
  VALUE exc = Qnil;
5116
5322
  do {
5117
5323
  couchbase::operations::query_index_drop_request req{};
5118
- exc = cb_extract_timeout(req, timeout);
5324
+ exc = cb_extract_timeout(req, options);
5119
5325
  if (!NIL_P(exc)) {
5120
5326
  break;
5121
5327
  }
5122
5328
  req.is_primary = true;
5123
5329
  req.bucket_name.assign(RSTRING_PTR(bucket_name), static_cast<size_t>(RSTRING_LEN(bucket_name)));
5124
5330
  if (!NIL_P(options)) {
5125
- Check_Type(options, T_HASH);
5126
5331
  VALUE ignore_if_does_not_exist = rb_hash_aref(options, rb_id2sym(rb_intern("ignore_if_does_not_exist")));
5127
5332
  if (ignore_if_does_not_exist == Qtrue) {
5128
5333
  req.ignore_if_does_not_exist = true;
@@ -5181,7 +5386,7 @@ cb_Backend_query_index_drop_primary(VALUE self, VALUE bucket_name, VALUE options
5181
5386
  }
5182
5387
 
5183
5388
  static VALUE
5184
- cb_Backend_query_index_build_deferred(VALUE self, VALUE bucket_name, VALUE timeout)
5389
+ cb_Backend_query_index_build_deferred(VALUE self, VALUE bucket_name, VALUE options)
5185
5390
  {
5186
5391
  cb_backend_data* backend = nullptr;
5187
5392
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -5192,11 +5397,14 @@ cb_Backend_query_index_build_deferred(VALUE self, VALUE bucket_name, VALUE timeo
5192
5397
  }
5193
5398
 
5194
5399
  Check_Type(bucket_name, T_STRING);
5400
+ if (!NIL_P(options)) {
5401
+ Check_Type(options, T_HASH);
5402
+ }
5195
5403
 
5196
5404
  VALUE exc = Qnil;
5197
5405
  do {
5198
5406
  couchbase::operations::query_index_build_deferred_request req{};
5199
- exc = cb_extract_timeout(req, timeout);
5407
+ exc = cb_extract_timeout(req, options);
5200
5408
  if (!NIL_P(exc)) {
5201
5409
  break;
5202
5410
  }
@@ -5273,7 +5481,7 @@ cb_extract_search_index(VALUE index, const couchbase::operations::search_index&
5273
5481
  }
5274
5482
 
5275
5483
  static VALUE
5276
- cb_Backend_search_index_get_all(VALUE self, VALUE timeout)
5484
+ cb_Backend_search_index_get_all(VALUE self, VALUE options)
5277
5485
  {
5278
5486
  cb_backend_data* backend = nullptr;
5279
5487
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -5286,7 +5494,7 @@ cb_Backend_search_index_get_all(VALUE self, VALUE timeout)
5286
5494
  VALUE exc = Qnil;
5287
5495
  do {
5288
5496
  couchbase::operations::search_index_get_all_request req{};
5289
- exc = cb_extract_timeout(req, timeout);
5497
+ exc = cb_extract_timeout(req, options);
5290
5498
  if (!NIL_P(exc)) {
5291
5499
  break;
5292
5500
  }
@@ -5922,7 +6130,9 @@ cb_Backend_document_search(VALUE self, VALUE index_name, VALUE query, VALUE opti
5922
6130
 
5923
6131
  Check_Type(index_name, T_STRING);
5924
6132
  Check_Type(query, T_STRING);
5925
- Check_Type(options, T_HASH);
6133
+ if (!NIL_P(options)) {
6134
+ Check_Type(options, T_HASH);
6135
+ }
5926
6136
 
5927
6137
  VALUE exc = Qnil;
5928
6138
  do {
@@ -6041,6 +6251,22 @@ cb_Backend_document_search(VALUE self, VALUE index_name, VALUE query, VALUE opti
6041
6251
  }
6042
6252
  }
6043
6253
 
6254
+ VALUE scope_name = rb_hash_aref(options, rb_id2sym(rb_intern("scope_name")));
6255
+ if (!NIL_P(scope_name) && TYPE(scope_name) == T_STRING) {
6256
+ req.scope_name.emplace(std::string(RSTRING_PTR(scope_name), static_cast<std::size_t>(RSTRING_LEN(scope_name))));
6257
+ VALUE collections = rb_hash_aref(options, rb_id2sym(rb_intern("collections")));
6258
+ if (!NIL_P(collections)) {
6259
+ Check_Type(collections, T_ARRAY);
6260
+ auto collections_size = static_cast<size_t>(RARRAY_LEN(collections));
6261
+ req.collections.reserve(collections_size);
6262
+ for (size_t i = 0; i < collections_size; ++i) {
6263
+ VALUE collection = rb_ary_entry(collections, static_cast<long>(i));
6264
+ Check_Type(collection, T_STRING);
6265
+ req.collections.emplace_back(std::string(RSTRING_PTR(collection), static_cast<std::size_t>(RSTRING_LEN(collection))));
6266
+ }
6267
+ }
6268
+ }
6269
+
6044
6270
  VALUE sort = rb_hash_aref(options, rb_id2sym(rb_intern("sort")));
6045
6271
  if (!NIL_P(sort)) {
6046
6272
  Check_Type(sort, T_ARRAY);
@@ -6271,7 +6497,7 @@ cb_Backend_dns_srv(VALUE self, VALUE hostname, VALUE service)
6271
6497
  }
6272
6498
 
6273
6499
  static VALUE
6274
- cb_Backend_analytics_get_pending_mutations(VALUE self, VALUE timeout)
6500
+ cb_Backend_analytics_get_pending_mutations(VALUE self, VALUE options)
6275
6501
  {
6276
6502
  cb_backend_data* backend = nullptr;
6277
6503
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -6284,7 +6510,7 @@ cb_Backend_analytics_get_pending_mutations(VALUE self, VALUE timeout)
6284
6510
  VALUE exc = Qnil;
6285
6511
  do {
6286
6512
  couchbase::operations::analytics_get_pending_mutations_request req{};
6287
- exc = cb_extract_timeout(req, timeout);
6513
+ exc = cb_extract_timeout(req, options);
6288
6514
  if (!NIL_P(exc)) {
6289
6515
  break;
6290
6516
  }
@@ -6315,7 +6541,7 @@ cb_Backend_analytics_get_pending_mutations(VALUE self, VALUE timeout)
6315
6541
  }
6316
6542
 
6317
6543
  static VALUE
6318
- cb_Backend_analytics_dataset_get_all(VALUE self, VALUE timeout)
6544
+ cb_Backend_analytics_dataset_get_all(VALUE self, VALUE options)
6319
6545
  {
6320
6546
  cb_backend_data* backend = nullptr;
6321
6547
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -6328,7 +6554,7 @@ cb_Backend_analytics_dataset_get_all(VALUE self, VALUE timeout)
6328
6554
  VALUE exc = Qnil;
6329
6555
  do {
6330
6556
  couchbase::operations::analytics_dataset_get_all_request req{};
6331
- exc = cb_extract_timeout(req, timeout);
6557
+ exc = cb_extract_timeout(req, options);
6332
6558
  if (!NIL_P(exc)) {
6333
6559
  break;
6334
6560
  }
@@ -6363,7 +6589,7 @@ cb_Backend_analytics_dataset_get_all(VALUE self, VALUE timeout)
6363
6589
  }
6364
6590
 
6365
6591
  static VALUE
6366
- cb_Backend_analytics_dataset_drop(VALUE self, VALUE dataset_name, VALUE dataverse_name, VALUE ignore_if_does_not_exist, VALUE timeout)
6592
+ cb_Backend_analytics_dataset_drop(VALUE self, VALUE dataset_name, VALUE options)
6367
6593
  {
6368
6594
  cb_backend_data* backend = nullptr;
6369
6595
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -6374,23 +6600,26 @@ cb_Backend_analytics_dataset_drop(VALUE self, VALUE dataset_name, VALUE datavers
6374
6600
  }
6375
6601
 
6376
6602
  Check_Type(dataset_name, T_STRING);
6377
- if (!NIL_P(dataverse_name)) {
6378
- Check_Type(dataverse_name, T_STRING);
6379
- }
6380
6603
 
6381
6604
  VALUE exc = Qnil;
6382
6605
  do {
6383
6606
  couchbase::operations::analytics_dataset_drop_request req{};
6384
- exc = cb_extract_timeout(req, timeout);
6607
+ exc = cb_extract_timeout(req, options);
6385
6608
  if (!NIL_P(exc)) {
6386
6609
  break;
6387
6610
  }
6388
6611
  req.dataset_name.assign(RSTRING_PTR(dataset_name), static_cast<size_t>(RSTRING_LEN(dataset_name)));
6612
+ VALUE dataverse_name = Qnil;
6613
+ exc = cb_extract_option_string(dataverse_name, options, "dataverse_name");
6614
+ if (!NIL_P(exc)) {
6615
+ break;
6616
+ }
6389
6617
  if (!NIL_P(dataverse_name)) {
6390
6618
  req.dataverse_name.assign(RSTRING_PTR(dataverse_name), static_cast<size_t>(RSTRING_LEN(dataverse_name)));
6391
6619
  }
6392
- if (!NIL_P(ignore_if_does_not_exist)) {
6393
- req.ignore_if_does_not_exist = RTEST(ignore_if_does_not_exist);
6620
+ exc = cb_extract_option_bool(req.ignore_if_does_not_exist, options, "ignore_if_does_not_exist");
6621
+ if (!NIL_P(exc)) {
6622
+ break;
6394
6623
  }
6395
6624
  auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_dataset_drop_response>>();
6396
6625
  auto f = barrier->get_future();
@@ -6418,13 +6647,7 @@ cb_Backend_analytics_dataset_drop(VALUE self, VALUE dataset_name, VALUE datavers
6418
6647
  }
6419
6648
 
6420
6649
  static VALUE
6421
- cb_Backend_analytics_dataset_create(VALUE self,
6422
- VALUE dataset_name,
6423
- VALUE bucket_name,
6424
- VALUE condition,
6425
- VALUE dataverse_name,
6426
- VALUE ignore_if_exists,
6427
- VALUE timeout)
6650
+ cb_Backend_analytics_dataset_create(VALUE self, VALUE dataset_name, VALUE bucket_name, VALUE options)
6428
6651
  {
6429
6652
  cb_backend_data* backend = nullptr;
6430
6653
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -6436,30 +6659,35 @@ cb_Backend_analytics_dataset_create(VALUE self,
6436
6659
 
6437
6660
  Check_Type(dataset_name, T_STRING);
6438
6661
  Check_Type(bucket_name, T_STRING);
6439
- if (!NIL_P(condition)) {
6440
- Check_Type(condition, T_STRING);
6441
- }
6442
- if (!NIL_P(dataverse_name)) {
6443
- Check_Type(dataverse_name, T_STRING);
6444
- }
6445
6662
 
6446
6663
  VALUE exc = Qnil;
6447
6664
  do {
6448
6665
  couchbase::operations::analytics_dataset_create_request req{};
6449
- exc = cb_extract_timeout(req, timeout);
6666
+ exc = cb_extract_timeout(req, options);
6450
6667
  if (!NIL_P(exc)) {
6451
6668
  break;
6452
6669
  }
6453
6670
  req.dataset_name.assign(RSTRING_PTR(dataset_name), static_cast<size_t>(RSTRING_LEN(dataset_name)));
6454
6671
  req.bucket_name.assign(RSTRING_PTR(bucket_name), static_cast<size_t>(RSTRING_LEN(bucket_name)));
6672
+ VALUE condition = Qnil;
6673
+ exc = cb_extract_option_string(condition, options, "condition");
6674
+ if (!NIL_P(exc)) {
6675
+ break;
6676
+ }
6455
6677
  if (!NIL_P(condition)) {
6456
6678
  req.condition.emplace(std::string(RSTRING_PTR(condition), static_cast<size_t>(RSTRING_LEN(condition))));
6457
6679
  }
6680
+ VALUE dataverse_name = Qnil;
6681
+ exc = cb_extract_option_string(dataverse_name, options, "dataverse_name");
6682
+ if (!NIL_P(exc)) {
6683
+ break;
6684
+ }
6458
6685
  if (!NIL_P(dataverse_name)) {
6459
6686
  req.dataverse_name.assign(RSTRING_PTR(dataverse_name), static_cast<size_t>(RSTRING_LEN(dataverse_name)));
6460
6687
  }
6461
- if (!NIL_P(ignore_if_exists)) {
6462
- req.ignore_if_exists = RTEST(ignore_if_exists);
6688
+ exc = cb_extract_option_bool(req.ignore_if_exists, options, "ignore_if_exists");
6689
+ if (!NIL_P(exc)) {
6690
+ break;
6463
6691
  }
6464
6692
  auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_dataset_create_response>>();
6465
6693
  auto f = barrier->get_future();
@@ -6487,7 +6715,7 @@ cb_Backend_analytics_dataset_create(VALUE self,
6487
6715
  }
6488
6716
 
6489
6717
  static VALUE
6490
- cb_Backend_analytics_dataverse_drop(VALUE self, VALUE dataverse_name, VALUE ignore_if_does_not_exist, VALUE timeout)
6718
+ cb_Backend_analytics_dataverse_drop(VALUE self, VALUE dataverse_name, VALUE options)
6491
6719
  {
6492
6720
  cb_backend_data* backend = nullptr;
6493
6721
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -6502,11 +6730,12 @@ cb_Backend_analytics_dataverse_drop(VALUE self, VALUE dataverse_name, VALUE igno
6502
6730
  VALUE exc = Qnil;
6503
6731
  do {
6504
6732
  couchbase::operations::analytics_dataverse_drop_request req{};
6505
- exc = cb_extract_timeout(req, timeout);
6733
+ exc = cb_extract_timeout(req, options);
6506
6734
  if (!NIL_P(exc)) {
6507
6735
  break;
6508
6736
  }
6509
6737
  req.dataverse_name.assign(RSTRING_PTR(dataverse_name), static_cast<size_t>(RSTRING_LEN(dataverse_name)));
6738
+ VALUE ignore_if_does_not_exist = rb_hash_aref(options, rb_id2sym(rb_intern("ignore_if_does_not_exist")));
6510
6739
  if (!NIL_P(ignore_if_does_not_exist)) {
6511
6740
  req.ignore_if_does_not_exist = RTEST(ignore_if_does_not_exist);
6512
6741
  }
@@ -6533,7 +6762,7 @@ cb_Backend_analytics_dataverse_drop(VALUE self, VALUE dataverse_name, VALUE igno
6533
6762
  }
6534
6763
 
6535
6764
  static VALUE
6536
- cb_Backend_analytics_dataverse_create(VALUE self, VALUE dataverse_name, VALUE ignore_if_exists, VALUE timeout)
6765
+ cb_Backend_analytics_dataverse_create(VALUE self, VALUE dataverse_name, VALUE options)
6537
6766
  {
6538
6767
  cb_backend_data* backend = nullptr;
6539
6768
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -6551,11 +6780,12 @@ cb_Backend_analytics_dataverse_create(VALUE self, VALUE dataverse_name, VALUE ig
6551
6780
  VALUE exc = Qnil;
6552
6781
  do {
6553
6782
  couchbase::operations::analytics_dataverse_create_request req{};
6554
- exc = cb_extract_timeout(req, timeout);
6783
+ exc = cb_extract_timeout(req, options);
6555
6784
  if (!NIL_P(exc)) {
6556
6785
  break;
6557
6786
  }
6558
6787
  req.dataverse_name.assign(RSTRING_PTR(dataverse_name), static_cast<size_t>(RSTRING_LEN(dataverse_name)));
6788
+ VALUE ignore_if_exists = rb_hash_aref(options, rb_id2sym(rb_intern("ignore_if_exists")));
6559
6789
  if (!NIL_P(ignore_if_exists)) {
6560
6790
  req.ignore_if_exists = RTEST(ignore_if_exists);
6561
6791
  }
@@ -6582,7 +6812,7 @@ cb_Backend_analytics_dataverse_create(VALUE self, VALUE dataverse_name, VALUE ig
6582
6812
  }
6583
6813
 
6584
6814
  static VALUE
6585
- cb_Backend_analytics_index_get_all(VALUE self, VALUE timeout)
6815
+ cb_Backend_analytics_index_get_all(VALUE self, VALUE options)
6586
6816
  {
6587
6817
  cb_backend_data* backend = nullptr;
6588
6818
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -6595,7 +6825,7 @@ cb_Backend_analytics_index_get_all(VALUE self, VALUE timeout)
6595
6825
  VALUE exc = Qnil;
6596
6826
  do {
6597
6827
  couchbase::operations::analytics_index_get_all_request req{};
6598
- exc = cb_extract_timeout(req, timeout);
6828
+ exc = cb_extract_timeout(req, options);
6599
6829
  if (!NIL_P(exc)) {
6600
6830
  break;
6601
6831
  }
@@ -6630,13 +6860,7 @@ cb_Backend_analytics_index_get_all(VALUE self, VALUE timeout)
6630
6860
  }
6631
6861
 
6632
6862
  static VALUE
6633
- cb_Backend_analytics_index_create(VALUE self,
6634
- VALUE index_name,
6635
- VALUE dataset_name,
6636
- VALUE fields,
6637
- VALUE dataverse_name,
6638
- VALUE ignore_if_exists,
6639
- VALUE timeout)
6863
+ cb_Backend_analytics_index_create(VALUE self, VALUE index_name, VALUE dataset_name, VALUE fields, VALUE options)
6640
6864
  {
6641
6865
  cb_backend_data* backend = nullptr;
6642
6866
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -6649,14 +6873,11 @@ cb_Backend_analytics_index_create(VALUE self,
6649
6873
  Check_Type(index_name, T_STRING);
6650
6874
  Check_Type(dataset_name, T_STRING);
6651
6875
  Check_Type(fields, T_ARRAY);
6652
- if (!NIL_P(dataverse_name)) {
6653
- Check_Type(dataverse_name, T_STRING);
6654
- }
6655
6876
 
6656
6877
  VALUE exc = Qnil;
6657
6878
  do {
6658
6879
  couchbase::operations::analytics_index_create_request req{};
6659
- exc = cb_extract_timeout(req, timeout);
6880
+ exc = cb_extract_timeout(req, options);
6660
6881
  if (!NIL_P(exc)) {
6661
6882
  break;
6662
6883
  }
@@ -6669,15 +6890,22 @@ cb_Backend_analytics_index_create(VALUE self,
6669
6890
  if (RARRAY_LEN(entry) == 2) {
6670
6891
  VALUE field = rb_ary_entry(entry, 0);
6671
6892
  VALUE type = rb_ary_entry(entry, 1);
6672
- req.fields.emplace(std::string(RSTRING_PTR(field), static_cast<std::size_t>(RSTRING_LEN(field))),
6673
- std::string(RSTRING_PTR(type), static_cast<std::size_t>(RSTRING_LEN(type))));
6893
+ req.fields.try_emplace(std::string(RSTRING_PTR(field), static_cast<std::size_t>(RSTRING_LEN(field))),
6894
+ std::string(RSTRING_PTR(type), static_cast<std::size_t>(RSTRING_LEN(type))));
6674
6895
  }
6675
6896
  }
6897
+
6898
+ VALUE dataverse_name = Qnil;
6899
+ exc = cb_extract_option_string(dataverse_name, options, "dataverse_name");
6900
+ if (!NIL_P(exc)) {
6901
+ break;
6902
+ }
6676
6903
  if (!NIL_P(dataverse_name)) {
6677
6904
  req.dataverse_name.assign(RSTRING_PTR(dataverse_name), static_cast<size_t>(RSTRING_LEN(dataverse_name)));
6678
6905
  }
6679
- if (!NIL_P(ignore_if_exists)) {
6680
- req.ignore_if_exists = RTEST(ignore_if_exists);
6906
+ exc = cb_extract_option_bool(req.ignore_if_exists, options, "ignore_if_exists");
6907
+ if (!NIL_P(exc)) {
6908
+ break;
6681
6909
  }
6682
6910
  auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_index_create_response>>();
6683
6911
  auto f = barrier->get_future();
@@ -6707,12 +6935,7 @@ cb_Backend_analytics_index_create(VALUE self,
6707
6935
  }
6708
6936
 
6709
6937
  static VALUE
6710
- cb_Backend_analytics_index_drop(VALUE self,
6711
- VALUE index_name,
6712
- VALUE dataset_name,
6713
- VALUE dataverse_name,
6714
- VALUE ignore_if_does_not_exist,
6715
- VALUE timeout)
6938
+ cb_Backend_analytics_index_drop(VALUE self, VALUE index_name, VALUE dataset_name, VALUE options)
6716
6939
  {
6717
6940
  cb_backend_data* backend = nullptr;
6718
6941
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -6724,24 +6947,27 @@ cb_Backend_analytics_index_drop(VALUE self,
6724
6947
 
6725
6948
  Check_Type(index_name, T_STRING);
6726
6949
  Check_Type(dataset_name, T_STRING);
6727
- if (!NIL_P(dataverse_name)) {
6728
- Check_Type(dataverse_name, T_STRING);
6729
- }
6730
6950
 
6731
6951
  VALUE exc = Qnil;
6732
6952
  do {
6733
6953
  couchbase::operations::analytics_index_drop_request req{};
6734
- exc = cb_extract_timeout(req, timeout);
6954
+ exc = cb_extract_timeout(req, options);
6735
6955
  if (!NIL_P(exc)) {
6736
6956
  break;
6737
6957
  }
6738
6958
  req.index_name.assign(RSTRING_PTR(index_name), static_cast<size_t>(RSTRING_LEN(index_name)));
6739
6959
  req.dataset_name.assign(RSTRING_PTR(dataset_name), static_cast<size_t>(RSTRING_LEN(dataset_name)));
6960
+ VALUE dataverse_name = Qnil;
6961
+ exc = cb_extract_option_string(dataverse_name, options, "dataverse_name");
6962
+ if (!NIL_P(exc)) {
6963
+ break;
6964
+ }
6740
6965
  if (!NIL_P(dataverse_name)) {
6741
6966
  req.dataverse_name.assign(RSTRING_PTR(dataverse_name), static_cast<size_t>(RSTRING_LEN(dataverse_name)));
6742
6967
  }
6743
- if (!NIL_P(ignore_if_does_not_exist)) {
6744
- req.ignore_if_does_not_exist = RTEST(ignore_if_does_not_exist);
6968
+ exc = cb_extract_option_bool(req.ignore_if_does_not_exist, options, "ignore_if_does_not_exist");
6969
+ if (!NIL_P(exc)) {
6970
+ break;
6745
6971
  }
6746
6972
  auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_index_drop_response>>();
6747
6973
  auto f = barrier->get_future();
@@ -6771,7 +6997,7 @@ cb_Backend_analytics_index_drop(VALUE self,
6771
6997
  }
6772
6998
 
6773
6999
  static VALUE
6774
- cb_Backend_analytics_link_connect(VALUE self, VALUE link_name, VALUE force, VALUE dataverse_name, VALUE timeout)
7000
+ cb_Backend_analytics_link_connect(VALUE self, VALUE options)
6775
7001
  {
6776
7002
  cb_backend_data* backend = nullptr;
6777
7003
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -6781,24 +7007,32 @@ cb_Backend_analytics_link_connect(VALUE self, VALUE link_name, VALUE force, VALU
6781
7007
  return Qnil;
6782
7008
  }
6783
7009
 
6784
- Check_Type(link_name, T_STRING);
6785
- if (!NIL_P(dataverse_name)) {
6786
- Check_Type(dataverse_name, T_STRING);
6787
- }
6788
-
6789
7010
  VALUE exc = Qnil;
6790
7011
  do {
6791
7012
  couchbase::operations::analytics_link_connect_request req{};
6792
- exc = cb_extract_timeout(req, timeout);
7013
+ exc = cb_extract_timeout(req, options);
7014
+ if (!NIL_P(exc)) {
7015
+ break;
7016
+ }
7017
+ VALUE link_name = Qnil;
7018
+ exc = cb_extract_option_string(link_name, options, "link_name");
7019
+ if (!NIL_P(exc)) {
7020
+ break;
7021
+ }
7022
+ if (!NIL_P(link_name)) {
7023
+ req.link_name.assign(RSTRING_PTR(link_name), static_cast<size_t>(RSTRING_LEN(link_name)));
7024
+ }
7025
+ VALUE dataverse_name = Qnil;
7026
+ exc = cb_extract_option_string(link_name, options, "dataverse_name");
6793
7027
  if (!NIL_P(exc)) {
6794
7028
  break;
6795
7029
  }
6796
- req.link_name.assign(RSTRING_PTR(link_name), static_cast<size_t>(RSTRING_LEN(link_name)));
6797
7030
  if (!NIL_P(dataverse_name)) {
6798
7031
  req.dataverse_name.assign(RSTRING_PTR(dataverse_name), static_cast<size_t>(RSTRING_LEN(dataverse_name)));
6799
7032
  }
6800
- if (!NIL_P(force)) {
6801
- req.force = RTEST(force);
7033
+ exc = cb_extract_option_bool(req.force, options, "force");
7034
+ if (!NIL_P(exc)) {
7035
+ break;
6802
7036
  }
6803
7037
  auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_link_connect_response>>();
6804
7038
  auto f = barrier->get_future();
@@ -6826,7 +7060,7 @@ cb_Backend_analytics_link_connect(VALUE self, VALUE link_name, VALUE force, VALU
6826
7060
  }
6827
7061
 
6828
7062
  static VALUE
6829
- cb_Backend_analytics_link_disconnect(VALUE self, VALUE link_name, VALUE dataverse_name, VALUE timeout)
7063
+ cb_Backend_analytics_link_disconnect(VALUE self, VALUE options)
6830
7064
  {
6831
7065
  cb_backend_data* backend = nullptr;
6832
7066
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -6836,19 +7070,26 @@ cb_Backend_analytics_link_disconnect(VALUE self, VALUE link_name, VALUE datavers
6836
7070
  return Qnil;
6837
7071
  }
6838
7072
 
6839
- Check_Type(link_name, T_STRING);
6840
- if (!NIL_P(dataverse_name)) {
6841
- Check_Type(dataverse_name, T_STRING);
6842
- }
6843
-
6844
7073
  VALUE exc = Qnil;
6845
7074
  do {
6846
7075
  couchbase::operations::analytics_link_disconnect_request req{};
6847
- exc = cb_extract_timeout(req, timeout);
7076
+ exc = cb_extract_timeout(req, options);
7077
+ if (!NIL_P(exc)) {
7078
+ break;
7079
+ }
7080
+ VALUE link_name = Qnil;
7081
+ exc = cb_extract_option_string(link_name, options, "link_name");
7082
+ if (!NIL_P(exc)) {
7083
+ break;
7084
+ }
7085
+ if (!NIL_P(link_name)) {
7086
+ req.link_name.assign(RSTRING_PTR(link_name), static_cast<size_t>(RSTRING_LEN(link_name)));
7087
+ }
7088
+ VALUE dataverse_name = Qnil;
7089
+ exc = cb_extract_option_string(link_name, options, "dataverse_name");
6848
7090
  if (!NIL_P(exc)) {
6849
7091
  break;
6850
7092
  }
6851
- req.link_name.assign(RSTRING_PTR(link_name), static_cast<size_t>(RSTRING_LEN(link_name)));
6852
7093
  if (!NIL_P(dataverse_name)) {
6853
7094
  req.dataverse_name.assign(RSTRING_PTR(dataverse_name), static_cast<size_t>(RSTRING_LEN(dataverse_name)));
6854
7095
  }
@@ -6877,42 +7118,606 @@ cb_Backend_analytics_link_disconnect(VALUE self, VALUE link_name, VALUE datavers
6877
7118
  return Qnil;
6878
7119
  }
6879
7120
 
6880
- static int
6881
- cb_for_each_named_param_analytics(VALUE key, VALUE value, VALUE arg)
6882
- {
6883
- auto* preq = reinterpret_cast<couchbase::operations::analytics_request*>(arg);
6884
- Check_Type(key, T_STRING);
6885
- Check_Type(value, T_STRING);
6886
- preq->named_parameters.emplace(
6887
- std::string_view(RSTRING_PTR(key), static_cast<std::size_t>(RSTRING_LEN(key))),
6888
- tao::json::from_string(std::string_view(RSTRING_PTR(value), static_cast<std::size_t>(RSTRING_LEN(value)))));
6889
- return ST_CONTINUE;
6890
- }
6891
-
6892
7121
  static VALUE
6893
- cb_Backend_document_analytics(VALUE self, VALUE statement, VALUE options)
7122
+ cb_fill_link(couchbase::operations::analytics_link::couchbase_remote& dst, VALUE src)
6894
7123
  {
6895
- cb_backend_data* backend = nullptr;
6896
- TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
7124
+ VALUE exc = Qnil;
6897
7125
 
6898
- if (!backend->cluster) {
6899
- rb_raise(rb_eArgError, "Cluster has been closed already");
6900
- return Qnil;
7126
+ exc = cb_extract_option_string(dst.link_name, src, "link_name");
7127
+ if (!NIL_P(exc)) {
7128
+ return exc;
6901
7129
  }
6902
-
6903
- Check_Type(statement, T_STRING);
6904
- Check_Type(options, T_HASH);
6905
-
6906
- VALUE exc = Qnil;
6907
- do {
6908
- couchbase::operations::analytics_request req;
6909
- req.statement.assign(RSTRING_PTR(statement), static_cast<size_t>(RSTRING_LEN(statement)));
6910
- VALUE client_context_id = rb_hash_aref(options, rb_id2sym(rb_intern("client_context_id")));
6911
- if (!NIL_P(client_context_id)) {
6912
- Check_Type(client_context_id, T_STRING);
6913
- req.client_context_id.assign(RSTRING_PTR(client_context_id), static_cast<size_t>(RSTRING_LEN(client_context_id)));
6914
- }
6915
- exc = cb_extract_timeout(req, options);
7130
+ exc = cb_extract_option_string(dst.dataverse, src, "dataverse");
7131
+ if (!NIL_P(exc)) {
7132
+ return exc;
7133
+ }
7134
+ exc = cb_extract_option_string(dst.hostname, src, "hostname");
7135
+ if (!NIL_P(exc)) {
7136
+ return exc;
7137
+ }
7138
+ exc = cb_extract_option_string(dst.username, src, "username");
7139
+ if (!NIL_P(exc)) {
7140
+ return exc;
7141
+ }
7142
+ exc = cb_extract_option_string(dst.password, src, "password");
7143
+ if (!NIL_P(exc)) {
7144
+ return exc;
7145
+ }
7146
+ VALUE encryption_level = Qnil;
7147
+ exc = cb_extract_option_symbol(encryption_level, src, "encryption_level");
7148
+ if (!NIL_P(exc)) {
7149
+ return exc;
7150
+ }
7151
+ if (NIL_P(encryption_level)) {
7152
+ encryption_level = rb_id2sym(rb_intern("none"));
7153
+ }
7154
+ ID level = rb_sym2id(encryption_level);
7155
+ if (level == rb_intern("none")) {
7156
+ dst.encryption.level = couchbase::operations::analytics_link::encryption_level::none;
7157
+ } else if (level == rb_intern("half")) {
7158
+ dst.encryption.level = couchbase::operations::analytics_link::encryption_level::half;
7159
+ } else if (level == rb_intern("full")) {
7160
+ dst.encryption.level = couchbase::operations::analytics_link::encryption_level::full;
7161
+ }
7162
+ exc = cb_extract_option_string(dst.encryption.certificate, src, "certificate");
7163
+ if (!NIL_P(exc)) {
7164
+ return exc;
7165
+ }
7166
+ exc = cb_extract_option_string(dst.encryption.client_certificate, src, "client_certificate");
7167
+ if (!NIL_P(exc)) {
7168
+ return exc;
7169
+ }
7170
+ exc = cb_extract_option_string(dst.encryption.client_key, src, "client_key");
7171
+ if (!NIL_P(exc)) {
7172
+ return exc;
7173
+ }
7174
+ return Qnil;
7175
+ }
7176
+
7177
+ static VALUE
7178
+ cb_fill_link(couchbase::operations::analytics_link::azure_blob_external& dst, VALUE src)
7179
+ {
7180
+ VALUE exc = Qnil;
7181
+
7182
+ exc = cb_extract_option_string(dst.link_name, src, "link_name");
7183
+ if (!NIL_P(exc)) {
7184
+ return exc;
7185
+ }
7186
+ exc = cb_extract_option_string(dst.dataverse, src, "dataverse");
7187
+ if (!NIL_P(exc)) {
7188
+ return exc;
7189
+ }
7190
+ exc = cb_extract_option_string(dst.connection_string, src, "connection_string");
7191
+ if (!NIL_P(exc)) {
7192
+ return exc;
7193
+ }
7194
+ exc = cb_extract_option_string(dst.account_name, src, "account_name");
7195
+ if (!NIL_P(exc)) {
7196
+ return exc;
7197
+ }
7198
+ exc = cb_extract_option_string(dst.account_key, src, "account_key");
7199
+ if (!NIL_P(exc)) {
7200
+ return exc;
7201
+ }
7202
+ exc = cb_extract_option_string(dst.shared_access_signature, src, "shared_access_signature");
7203
+ if (!NIL_P(exc)) {
7204
+ return exc;
7205
+ }
7206
+ exc = cb_extract_option_string(dst.blob_endpoint, src, "blob_endpoint");
7207
+ if (!NIL_P(exc)) {
7208
+ return exc;
7209
+ }
7210
+ exc = cb_extract_option_string(dst.endpoint_suffix, src, "endpoint_suffix");
7211
+ if (!NIL_P(exc)) {
7212
+ return exc;
7213
+ }
7214
+ return Qnil;
7215
+ }
7216
+
7217
+ static VALUE
7218
+ cb_fill_link(couchbase::operations::analytics_link::s3_external& dst, VALUE src)
7219
+ {
7220
+ VALUE exc = Qnil;
7221
+
7222
+ exc = cb_extract_option_string(dst.link_name, src, "link_name");
7223
+ if (!NIL_P(exc)) {
7224
+ return exc;
7225
+ }
7226
+ exc = cb_extract_option_string(dst.dataverse, src, "dataverse");
7227
+ if (!NIL_P(exc)) {
7228
+ return exc;
7229
+ }
7230
+ exc = cb_extract_option_string(dst.access_key_id, src, "access_key_id");
7231
+ if (!NIL_P(exc)) {
7232
+ return exc;
7233
+ }
7234
+ exc = cb_extract_option_string(dst.secret_access_key, src, "secret_access_key");
7235
+ if (!NIL_P(exc)) {
7236
+ return exc;
7237
+ }
7238
+ exc = cb_extract_option_string(dst.session_token, src, "session_token");
7239
+ if (!NIL_P(exc)) {
7240
+ return exc;
7241
+ }
7242
+ exc = cb_extract_option_string(dst.region, src, "region");
7243
+ if (!NIL_P(exc)) {
7244
+ return exc;
7245
+ }
7246
+ exc = cb_extract_option_string(dst.service_endpoint, src, "service_endpoint");
7247
+ if (!NIL_P(exc)) {
7248
+ return exc;
7249
+ }
7250
+ return Qnil;
7251
+ }
7252
+
7253
+ static VALUE
7254
+ cb_Backend_analytics_link_create(VALUE self, VALUE link, VALUE options)
7255
+ {
7256
+ cb_backend_data* backend = nullptr;
7257
+ TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
7258
+
7259
+ if (!backend->cluster) {
7260
+ rb_raise(rb_eArgError, "Cluster has been closed already");
7261
+ return Qnil;
7262
+ }
7263
+
7264
+ if (!NIL_P(options)) {
7265
+ Check_Type(options, T_HASH);
7266
+ }
7267
+
7268
+ VALUE exc = Qnil;
7269
+ do {
7270
+ VALUE link_type = Qnil;
7271
+ exc = cb_extract_option_symbol(link_type, link, "type");
7272
+ if (!NIL_P(exc)) {
7273
+ return exc;
7274
+ }
7275
+
7276
+ ID type = rb_sym2id(link_type);
7277
+ if (type == rb_intern("couchbase")) {
7278
+ couchbase::operations::analytics_link_create_request<couchbase::operations::analytics_link::couchbase_remote> req{};
7279
+ exc = cb_extract_timeout(req, options);
7280
+ if (!NIL_P(exc)) {
7281
+ break;
7282
+ }
7283
+ exc = cb_fill_link(req.link, link);
7284
+ if (!NIL_P(exc)) {
7285
+ break;
7286
+ }
7287
+
7288
+ auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_link_create_response>>();
7289
+ auto f = barrier->get_future();
7290
+ backend->cluster->execute_http(
7291
+ req, [barrier](couchbase::operations::analytics_link_create_response&& resp) mutable { barrier->set_value(resp); });
7292
+ auto resp = cb_wait_for_future(f);
7293
+
7294
+ if (resp.ctx.ec) {
7295
+ if (resp.errors.empty()) {
7296
+ exc = cb_map_error_code(
7297
+ resp.ctx, fmt::format("unable to create couchbase_remote link `{}` on `{}`", req.link.link_name, req.link.dataverse));
7298
+ } else {
7299
+ const auto& first_error = resp.errors.front();
7300
+ exc = cb_map_error_code(resp.ctx,
7301
+ fmt::format("unable to create couchbase_remote link `{}` on `{}` ({}: {})",
7302
+ req.link.link_name,
7303
+ req.link.dataverse,
7304
+ first_error.code,
7305
+ first_error.message));
7306
+ }
7307
+ break;
7308
+ }
7309
+
7310
+ } else if (type == rb_intern("azureblob")) {
7311
+ couchbase::operations::analytics_link_create_request<couchbase::operations::analytics_link::azure_blob_external> req{};
7312
+ exc = cb_extract_timeout(req, options);
7313
+ if (!NIL_P(exc)) {
7314
+ break;
7315
+ }
7316
+
7317
+ exc = cb_fill_link(req.link, link);
7318
+ if (!NIL_P(exc)) {
7319
+ break;
7320
+ }
7321
+
7322
+ auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_link_create_response>>();
7323
+ auto f = barrier->get_future();
7324
+ backend->cluster->execute_http(
7325
+ req, [barrier](couchbase::operations::analytics_link_create_response&& resp) mutable { barrier->set_value(resp); });
7326
+ auto resp = cb_wait_for_future(f);
7327
+
7328
+ if (resp.ctx.ec) {
7329
+ if (resp.errors.empty()) {
7330
+ exc = cb_map_error_code(
7331
+ resp.ctx,
7332
+ fmt::format("unable to create azure_blob_external link `{}` on `{}`", req.link.link_name, req.link.dataverse));
7333
+ } else {
7334
+ const auto& first_error = resp.errors.front();
7335
+ exc = cb_map_error_code(resp.ctx,
7336
+ fmt::format("unable to create azure_blob_external link `{}` on `{}` ({}: {})",
7337
+ req.link.link_name,
7338
+ req.link.dataverse,
7339
+ first_error.code,
7340
+ first_error.message));
7341
+ }
7342
+ break;
7343
+ }
7344
+
7345
+ } else if (type == rb_intern("s3")) {
7346
+ couchbase::operations::analytics_link_create_request<couchbase::operations::analytics_link::s3_external> req{};
7347
+ exc = cb_extract_timeout(req, options);
7348
+ if (!NIL_P(exc)) {
7349
+ break;
7350
+ }
7351
+
7352
+ exc = cb_fill_link(req.link, link);
7353
+ if (!NIL_P(exc)) {
7354
+ break;
7355
+ }
7356
+
7357
+ auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_link_create_response>>();
7358
+ auto f = barrier->get_future();
7359
+ backend->cluster->execute_http(
7360
+ req, [barrier](couchbase::operations::analytics_link_create_response&& resp) mutable { barrier->set_value(resp); });
7361
+ auto resp = cb_wait_for_future(f);
7362
+
7363
+ if (resp.ctx.ec) {
7364
+ if (resp.errors.empty()) {
7365
+ exc = cb_map_error_code(
7366
+ resp.ctx, fmt::format("unable to create s3_external link `{}` on `{}`", req.link.link_name, req.link.dataverse));
7367
+ } else {
7368
+ const auto& first_error = resp.errors.front();
7369
+ exc = cb_map_error_code(resp.ctx,
7370
+ fmt::format("unable to create s3_external link `{}` on `{}` ({}: {})",
7371
+ req.link.link_name,
7372
+ req.link.dataverse,
7373
+ first_error.code,
7374
+ first_error.message));
7375
+ }
7376
+ break;
7377
+ }
7378
+ }
7379
+
7380
+ return Qtrue;
7381
+ } while (false);
7382
+ rb_exc_raise(exc);
7383
+ return Qnil;
7384
+ }
7385
+
7386
+ static VALUE
7387
+ cb_Backend_analytics_link_replace(VALUE self, VALUE link, VALUE options)
7388
+ {
7389
+ cb_backend_data* backend = nullptr;
7390
+ TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
7391
+
7392
+ if (!backend->cluster) {
7393
+ rb_raise(rb_eArgError, "Cluster has been closed already");
7394
+ return Qnil;
7395
+ }
7396
+
7397
+ if (!NIL_P(options)) {
7398
+ Check_Type(options, T_HASH);
7399
+ }
7400
+
7401
+ VALUE exc = Qnil;
7402
+ do {
7403
+ VALUE link_type = Qnil;
7404
+ exc = cb_extract_option_symbol(link_type, link, "type");
7405
+ if (!NIL_P(exc)) {
7406
+ return exc;
7407
+ }
7408
+
7409
+ ID type = rb_sym2id(link_type);
7410
+ if (type == rb_intern("couchbase")) {
7411
+ couchbase::operations::analytics_link_replace_request<couchbase::operations::analytics_link::couchbase_remote> req{};
7412
+ exc = cb_extract_timeout(req, options);
7413
+ if (!NIL_P(exc)) {
7414
+ break;
7415
+ }
7416
+ exc = cb_fill_link(req.link, link);
7417
+ if (!NIL_P(exc)) {
7418
+ break;
7419
+ }
7420
+
7421
+ auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_link_replace_response>>();
7422
+ auto f = barrier->get_future();
7423
+ backend->cluster->execute_http(
7424
+ req, [barrier](couchbase::operations::analytics_link_replace_response&& resp) mutable { barrier->set_value(resp); });
7425
+ auto resp = cb_wait_for_future(f);
7426
+
7427
+ if (resp.ctx.ec) {
7428
+ if (resp.errors.empty()) {
7429
+ exc = cb_map_error_code(
7430
+ resp.ctx,
7431
+ fmt::format("unable to replace couchbase_remote link `{}` on `{}`", req.link.link_name, req.link.dataverse));
7432
+ } else {
7433
+ const auto& first_error = resp.errors.front();
7434
+ exc = cb_map_error_code(resp.ctx,
7435
+ fmt::format("unable to replace couchbase_remote link `{}` on `{}` ({}: {})",
7436
+ req.link.link_name,
7437
+ req.link.dataverse,
7438
+ first_error.code,
7439
+ first_error.message));
7440
+ }
7441
+ break;
7442
+ }
7443
+
7444
+ } else if (type == rb_intern("azureblob")) {
7445
+ couchbase::operations::analytics_link_replace_request<couchbase::operations::analytics_link::azure_blob_external> req{};
7446
+ exc = cb_extract_timeout(req, options);
7447
+ if (!NIL_P(exc)) {
7448
+ break;
7449
+ }
7450
+
7451
+ exc = cb_fill_link(req.link, link);
7452
+ if (!NIL_P(exc)) {
7453
+ break;
7454
+ }
7455
+
7456
+ auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_link_replace_response>>();
7457
+ auto f = barrier->get_future();
7458
+ backend->cluster->execute_http(
7459
+ req, [barrier](couchbase::operations::analytics_link_replace_response&& resp) mutable { barrier->set_value(resp); });
7460
+ auto resp = cb_wait_for_future(f);
7461
+
7462
+ if (resp.ctx.ec) {
7463
+ if (resp.errors.empty()) {
7464
+ exc = cb_map_error_code(
7465
+ resp.ctx,
7466
+ fmt::format("unable to replace azure_blob_external link `{}` on `{}`", req.link.link_name, req.link.dataverse));
7467
+ } else {
7468
+ const auto& first_error = resp.errors.front();
7469
+ exc = cb_map_error_code(resp.ctx,
7470
+ fmt::format("unable to replace azure_blob_external link `{}` on `{}` ({}: {})",
7471
+ req.link.link_name,
7472
+ req.link.dataverse,
7473
+ first_error.code,
7474
+ first_error.message));
7475
+ }
7476
+ break;
7477
+ }
7478
+
7479
+ } else if (type == rb_intern("s3")) {
7480
+ couchbase::operations::analytics_link_replace_request<couchbase::operations::analytics_link::s3_external> req{};
7481
+ exc = cb_extract_timeout(req, options);
7482
+ if (!NIL_P(exc)) {
7483
+ break;
7484
+ }
7485
+
7486
+ exc = cb_fill_link(req.link, link);
7487
+ if (!NIL_P(exc)) {
7488
+ break;
7489
+ }
7490
+
7491
+ auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_link_replace_response>>();
7492
+ auto f = barrier->get_future();
7493
+ backend->cluster->execute_http(
7494
+ req, [barrier](couchbase::operations::analytics_link_replace_response&& resp) mutable { barrier->set_value(resp); });
7495
+ auto resp = cb_wait_for_future(f);
7496
+
7497
+ if (resp.ctx.ec) {
7498
+ if (resp.errors.empty()) {
7499
+ exc = cb_map_error_code(
7500
+ resp.ctx, fmt::format("unable to replace s3_external link `{}` on `{}`", req.link.link_name, req.link.dataverse));
7501
+ } else {
7502
+ const auto& first_error = resp.errors.front();
7503
+ exc = cb_map_error_code(resp.ctx,
7504
+ fmt::format("unable to replace s3_external link `{}` on `{}` ({}: {})",
7505
+ req.link.link_name,
7506
+ req.link.dataverse,
7507
+ first_error.code,
7508
+ first_error.message));
7509
+ }
7510
+ break;
7511
+ }
7512
+ }
7513
+
7514
+ return Qtrue;
7515
+ } while (false);
7516
+ rb_exc_raise(exc);
7517
+ return Qnil;
7518
+ }
7519
+
7520
+ static VALUE
7521
+ cb_Backend_analytics_link_drop(VALUE self, VALUE link, VALUE dataverse, VALUE options)
7522
+ {
7523
+ cb_backend_data* backend = nullptr;
7524
+ TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
7525
+
7526
+ if (!backend->cluster) {
7527
+ rb_raise(rb_eArgError, "Cluster has been closed already");
7528
+ return Qnil;
7529
+ }
7530
+
7531
+ Check_Type(link, T_STRING);
7532
+ Check_Type(dataverse, T_STRING);
7533
+ if (!NIL_P(options)) {
7534
+ Check_Type(options, T_HASH);
7535
+ }
7536
+
7537
+ VALUE exc = Qnil;
7538
+ do {
7539
+ couchbase::operations::analytics_link_drop_request req{};
7540
+ exc = cb_extract_timeout(req, options);
7541
+ if (!NIL_P(exc)) {
7542
+ break;
7543
+ }
7544
+
7545
+ req.link_name.assign(RSTRING_PTR(link), static_cast<size_t>(RSTRING_LEN(link)));
7546
+ req.dataverse_name.assign(RSTRING_PTR(dataverse), static_cast<size_t>(RSTRING_LEN(dataverse)));
7547
+
7548
+ auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_link_drop_response>>();
7549
+ auto f = barrier->get_future();
7550
+ backend->cluster->execute_http(
7551
+ req, [barrier](couchbase::operations::analytics_link_drop_response&& resp) mutable { barrier->set_value(resp); });
7552
+ auto resp = cb_wait_for_future(f);
7553
+
7554
+ if (resp.ctx.ec) {
7555
+ if (resp.errors.empty()) {
7556
+ exc = cb_map_error_code(resp.ctx, fmt::format("unable to drop link `{}` on `{}`", req.link_name, req.dataverse_name));
7557
+ } else {
7558
+ const auto& first_error = resp.errors.front();
7559
+ exc = cb_map_error_code(
7560
+ resp.ctx,
7561
+ fmt::format(
7562
+ "unable to drop link `{}` on `{}` ({}: {})", req.link_name, req.dataverse_name, first_error.code, first_error.message));
7563
+ }
7564
+ break;
7565
+ }
7566
+
7567
+ return Qtrue;
7568
+ } while (false);
7569
+ rb_exc_raise(exc);
7570
+ return Qnil;
7571
+ }
7572
+
7573
+ static VALUE
7574
+ cb_Backend_analytics_link_get_all(VALUE self, VALUE options)
7575
+ {
7576
+ cb_backend_data* backend = nullptr;
7577
+ TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
7578
+
7579
+ if (!backend->cluster) {
7580
+ rb_raise(rb_eArgError, "Cluster has been closed already");
7581
+ return Qnil;
7582
+ }
7583
+
7584
+ if (!NIL_P(options)) {
7585
+ Check_Type(options, T_HASH);
7586
+ }
7587
+
7588
+ VALUE exc = Qnil;
7589
+ do {
7590
+ couchbase::operations::analytics_link_get_all_request req{};
7591
+ exc = cb_extract_timeout(req, options);
7592
+ if (!NIL_P(exc)) {
7593
+ break;
7594
+ }
7595
+
7596
+ exc = cb_extract_option_string(req.link_type, options, "link_type");
7597
+ if (!NIL_P(exc)) {
7598
+ return exc;
7599
+ }
7600
+ exc = cb_extract_option_string(req.dataverse_name, options, "dataverse");
7601
+ if (!NIL_P(exc)) {
7602
+ return exc;
7603
+ }
7604
+ exc = cb_extract_option_string(req.link_name, options, "link_name");
7605
+ if (!NIL_P(exc)) {
7606
+ return exc;
7607
+ }
7608
+
7609
+ auto barrier = std::make_shared<std::promise<couchbase::operations::analytics_link_get_all_response>>();
7610
+ auto f = barrier->get_future();
7611
+ backend->cluster->execute_http(
7612
+ req, [barrier](couchbase::operations::analytics_link_get_all_response&& resp) mutable { barrier->set_value(resp); });
7613
+ auto resp = cb_wait_for_future(f);
7614
+
7615
+ if (resp.ctx.ec) {
7616
+ if (resp.errors.empty()) {
7617
+ exc = cb_map_error_code(
7618
+ resp.ctx,
7619
+ fmt::format(
7620
+ R"(unable to retrieve links type={}, dataverse="{}", name="{}")", req.link_type, req.link_name, req.dataverse_name));
7621
+ } else {
7622
+ const auto& first_error = resp.errors.front();
7623
+ exc = cb_map_error_code(resp.ctx,
7624
+ fmt::format(R"(unable to retrieve links type={}, dataverse="{}", name="{}" ({}: {}))",
7625
+ req.link_type,
7626
+ req.link_name,
7627
+ req.dataverse_name,
7628
+ first_error.code,
7629
+ first_error.message));
7630
+ }
7631
+ break;
7632
+ }
7633
+
7634
+ VALUE res = rb_ary_new_capa(static_cast<long>(resp.couchbase.size() + resp.s3.size() + resp.azure_blob.size()));
7635
+ for (const auto& link : resp.couchbase) {
7636
+ VALUE row = rb_hash_new();
7637
+ rb_hash_aset(row, rb_id2sym(rb_intern("type")), rb_id2sym(rb_intern("couchbase")));
7638
+ rb_hash_aset(row, rb_id2sym(rb_intern("dataverse")), cb_str_new(link.dataverse));
7639
+ rb_hash_aset(row, rb_id2sym(rb_intern("link_name")), cb_str_new(link.link_name));
7640
+ rb_hash_aset(row, rb_id2sym(rb_intern("hostname")), cb_str_new(link.hostname));
7641
+ switch (link.encryption.level) {
7642
+ case couchbase::operations::analytics_link::encryption_level::none:
7643
+ rb_hash_aset(row, rb_id2sym(rb_intern("encryption_level")), rb_id2sym(rb_intern("none")));
7644
+ break;
7645
+ case couchbase::operations::analytics_link::encryption_level::half:
7646
+ rb_hash_aset(row, rb_id2sym(rb_intern("encryption_level")), rb_id2sym(rb_intern("half")));
7647
+ break;
7648
+ case couchbase::operations::analytics_link::encryption_level::full:
7649
+ rb_hash_aset(row, rb_id2sym(rb_intern("encryption_level")), rb_id2sym(rb_intern("full")));
7650
+ break;
7651
+ }
7652
+ rb_hash_aset(row, rb_id2sym(rb_intern("username")), cb_str_new(link.username));
7653
+ rb_hash_aset(row, rb_id2sym(rb_intern("certificate")), cb_str_new(link.encryption.certificate));
7654
+ rb_hash_aset(row, rb_id2sym(rb_intern("client_certificate")), cb_str_new(link.encryption.client_certificate));
7655
+ rb_ary_push(res, row);
7656
+ }
7657
+ for (const auto& link : resp.s3) {
7658
+ VALUE row = rb_hash_new();
7659
+ rb_hash_aset(row, rb_id2sym(rb_intern("type")), rb_id2sym(rb_intern("s3")));
7660
+ rb_hash_aset(row, rb_id2sym(rb_intern("dataverse")), cb_str_new(link.dataverse));
7661
+ rb_hash_aset(row, rb_id2sym(rb_intern("link_name")), cb_str_new(link.link_name));
7662
+ rb_hash_aset(row, rb_id2sym(rb_intern("access_key_id")), cb_str_new(link.access_key_id));
7663
+ rb_hash_aset(row, rb_id2sym(rb_intern("region")), cb_str_new(link.region));
7664
+ rb_hash_aset(row, rb_id2sym(rb_intern("service_endpoint")), cb_str_new(link.service_endpoint));
7665
+ rb_ary_push(res, row);
7666
+ }
7667
+ for (const auto& link : resp.azure_blob) {
7668
+ VALUE row = rb_hash_new();
7669
+ rb_hash_aset(row, rb_id2sym(rb_intern("type")), rb_id2sym(rb_intern("azureblob")));
7670
+ rb_hash_aset(row, rb_id2sym(rb_intern("dataverse")), cb_str_new(link.dataverse));
7671
+ rb_hash_aset(row, rb_id2sym(rb_intern("link_name")), cb_str_new(link.link_name));
7672
+ rb_hash_aset(row, rb_id2sym(rb_intern("account_name")), cb_str_new(link.account_name));
7673
+ rb_hash_aset(row, rb_id2sym(rb_intern("blob_endpoint")), cb_str_new(link.blob_endpoint));
7674
+ rb_hash_aset(row, rb_id2sym(rb_intern("endpoint_suffix")), cb_str_new(link.endpoint_suffix));
7675
+ rb_ary_push(res, row);
7676
+ }
7677
+
7678
+ return res;
7679
+ } while (false);
7680
+ rb_exc_raise(exc);
7681
+ return Qnil;
7682
+ }
7683
+ static int
7684
+ cb_for_each_named_param_analytics(VALUE key, VALUE value, VALUE arg)
7685
+ {
7686
+ auto* preq = reinterpret_cast<couchbase::operations::analytics_request*>(arg);
7687
+ Check_Type(key, T_STRING);
7688
+ Check_Type(value, T_STRING);
7689
+ preq->named_parameters.emplace(
7690
+ std::string_view(RSTRING_PTR(key), static_cast<std::size_t>(RSTRING_LEN(key))),
7691
+ tao::json::from_string(std::string_view(RSTRING_PTR(value), static_cast<std::size_t>(RSTRING_LEN(value)))));
7692
+ return ST_CONTINUE;
7693
+ }
7694
+
7695
+ static VALUE
7696
+ cb_Backend_document_analytics(VALUE self, VALUE statement, VALUE options)
7697
+ {
7698
+ cb_backend_data* backend = nullptr;
7699
+ TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
7700
+
7701
+ if (!backend->cluster) {
7702
+ rb_raise(rb_eArgError, "Cluster has been closed already");
7703
+ return Qnil;
7704
+ }
7705
+
7706
+ Check_Type(statement, T_STRING);
7707
+ if (!NIL_P(options)) {
7708
+ Check_Type(options, T_HASH);
7709
+ }
7710
+
7711
+ VALUE exc = Qnil;
7712
+ do {
7713
+ couchbase::operations::analytics_request req;
7714
+ req.statement.assign(RSTRING_PTR(statement), static_cast<size_t>(RSTRING_LEN(statement)));
7715
+ VALUE client_context_id = rb_hash_aref(options, rb_id2sym(rb_intern("client_context_id")));
7716
+ if (!NIL_P(client_context_id)) {
7717
+ Check_Type(client_context_id, T_STRING);
7718
+ req.client_context_id.assign(RSTRING_PTR(client_context_id), static_cast<size_t>(RSTRING_LEN(client_context_id)));
7719
+ }
7720
+ exc = cb_extract_timeout(req, options);
6916
7721
  if (!NIL_P(exc)) {
6917
7722
  break;
6918
7723
  }
@@ -6993,7 +7798,7 @@ cb_Backend_document_analytics(VALUE self, VALUE statement, VALUE options)
6993
7798
  VALUE res = rb_hash_new();
6994
7799
  VALUE rows = rb_ary_new_capa(static_cast<long>(resp.payload.rows.size()));
6995
7800
  rb_hash_aset(res, rb_id2sym(rb_intern("rows")), rows);
6996
- for (auto& row : resp.payload.rows) {
7801
+ for (const auto& row : resp.payload.rows) {
6997
7802
  rb_ary_push(rows, cb_str_new(row));
6998
7803
  }
6999
7804
  VALUE meta = rb_hash_new();
@@ -7686,6 +8491,48 @@ cb_Backend_leb128_decode(VALUE self, VALUE data)
7686
8491
  return Qnil;
7687
8492
  }
7688
8493
 
8494
+ static VALUE
8495
+ cb_Backend_query_escape(VALUE self, VALUE data)
8496
+ {
8497
+ (void)self;
8498
+ Check_Type(data, T_STRING);
8499
+ auto encoded =
8500
+ couchbase::utils::string_codec::v2::query_escape(std::string(RSTRING_PTR(data), static_cast<std::size_t>(RSTRING_LEN(data))));
8501
+ return cb_str_new(encoded);
8502
+ }
8503
+
8504
+ static VALUE
8505
+ cb_Backend_path_escape(VALUE self, VALUE data)
8506
+ {
8507
+ (void)self;
8508
+ Check_Type(data, T_STRING);
8509
+ auto encoded =
8510
+ couchbase::utils::string_codec::v2::path_escape(std::string(RSTRING_PTR(data), static_cast<std::size_t>(RSTRING_LEN(data))));
8511
+ return cb_str_new(encoded);
8512
+ }
8513
+
8514
+ static int
8515
+ cb_for_each_form_encode_value(VALUE key, VALUE value, VALUE arg)
8516
+ {
8517
+ auto* values = reinterpret_cast<std::map<std::string, std::string>*>(arg);
8518
+ VALUE key_str = rb_obj_as_string(key);
8519
+ VALUE value_str = rb_obj_as_string(value);
8520
+ values->emplace(std::string(RSTRING_PTR(key_str), static_cast<std::size_t>(RSTRING_LEN(key_str))),
8521
+ std::string(RSTRING_PTR(value_str), static_cast<std::size_t>(RSTRING_LEN(value_str))));
8522
+ return ST_CONTINUE;
8523
+ }
8524
+
8525
+ static VALUE
8526
+ cb_Backend_form_encode(VALUE self, VALUE data)
8527
+ {
8528
+ (void)self;
8529
+ Check_Type(data, T_HASH);
8530
+ std::map<std::string, std::string> values{};
8531
+ rb_hash_foreach(data, INT_FUNC(cb_for_each_form_encode_value), reinterpret_cast<VALUE>(&values));
8532
+ auto encoded = couchbase::utils::string_codec::v2::form_encode(values);
8533
+ return cb_str_new(encoded);
8534
+ }
8535
+
7689
8536
  static void
7690
8537
  init_backend(VALUE mCouchbase)
7691
8538
  {
@@ -7748,10 +8595,10 @@ init_backend(VALUE mCouchbase)
7748
8595
  rb_define_method(cBackend, "collection_drop", VALUE_FUNC(cb_Backend_collection_drop), 4);
7749
8596
 
7750
8597
  rb_define_method(cBackend, "query_index_get_all", VALUE_FUNC(cb_Backend_query_index_get_all), 2);
7751
- rb_define_method(cBackend, "query_index_create", VALUE_FUNC(cb_Backend_query_index_create), 5);
7752
- rb_define_method(cBackend, "query_index_create_primary", VALUE_FUNC(cb_Backend_query_index_create_primary), 3);
7753
- rb_define_method(cBackend, "query_index_drop", VALUE_FUNC(cb_Backend_query_index_drop), 4);
7754
- rb_define_method(cBackend, "query_index_drop_primary", VALUE_FUNC(cb_Backend_query_index_drop_primary), 3);
8598
+ rb_define_method(cBackend, "query_index_create", VALUE_FUNC(cb_Backend_query_index_create), 4);
8599
+ rb_define_method(cBackend, "query_index_create_primary", VALUE_FUNC(cb_Backend_query_index_create_primary), 2);
8600
+ rb_define_method(cBackend, "query_index_drop", VALUE_FUNC(cb_Backend_query_index_drop), 3);
8601
+ rb_define_method(cBackend, "query_index_drop_primary", VALUE_FUNC(cb_Backend_query_index_drop_primary), 2);
7755
8602
  rb_define_method(cBackend, "query_index_build_deferred", VALUE_FUNC(cb_Backend_query_index_build_deferred), 2);
7756
8603
  rb_define_method(cBackend, "query_index_watch", VALUE_FUNC(cb_Backend_query_index_watch), 4);
7757
8604
 
@@ -7771,16 +8618,20 @@ init_backend(VALUE mCouchbase)
7771
8618
  rb_define_method(cBackend, "search_index_analyze_document", VALUE_FUNC(cb_Backend_search_index_analyze_document), 3);
7772
8619
 
7773
8620
  rb_define_method(cBackend, "analytics_get_pending_mutations", VALUE_FUNC(cb_Backend_analytics_get_pending_mutations), 1);
7774
- rb_define_method(cBackend, "analytics_dataverse_drop", VALUE_FUNC(cb_Backend_analytics_dataverse_drop), 3);
7775
- rb_define_method(cBackend, "analytics_dataverse_create", VALUE_FUNC(cb_Backend_analytics_dataverse_create), 3);
7776
- rb_define_method(cBackend, "analytics_dataset_create", VALUE_FUNC(cb_Backend_analytics_dataset_create), 6);
7777
- rb_define_method(cBackend, "analytics_dataset_drop", VALUE_FUNC(cb_Backend_analytics_dataset_drop), 4);
8621
+ rb_define_method(cBackend, "analytics_dataverse_drop", VALUE_FUNC(cb_Backend_analytics_dataverse_drop), 2);
8622
+ rb_define_method(cBackend, "analytics_dataverse_create", VALUE_FUNC(cb_Backend_analytics_dataverse_create), 2);
8623
+ rb_define_method(cBackend, "analytics_dataset_create", VALUE_FUNC(cb_Backend_analytics_dataset_create), 3);
8624
+ rb_define_method(cBackend, "analytics_dataset_drop", VALUE_FUNC(cb_Backend_analytics_dataset_drop), 2);
7778
8625
  rb_define_method(cBackend, "analytics_dataset_get_all", VALUE_FUNC(cb_Backend_analytics_dataset_get_all), 1);
7779
8626
  rb_define_method(cBackend, "analytics_index_get_all", VALUE_FUNC(cb_Backend_analytics_index_get_all), 1);
7780
- rb_define_method(cBackend, "analytics_index_create", VALUE_FUNC(cb_Backend_analytics_index_create), 6);
7781
- rb_define_method(cBackend, "analytics_index_drop", VALUE_FUNC(cb_Backend_analytics_index_drop), 5);
7782
- rb_define_method(cBackend, "analytics_link_connect", VALUE_FUNC(cb_Backend_analytics_link_connect), 4);
7783
- rb_define_method(cBackend, "analytics_link_disconnect", VALUE_FUNC(cb_Backend_analytics_link_disconnect), 3);
8627
+ rb_define_method(cBackend, "analytics_index_create", VALUE_FUNC(cb_Backend_analytics_index_create), 4);
8628
+ rb_define_method(cBackend, "analytics_index_drop", VALUE_FUNC(cb_Backend_analytics_index_drop), 3);
8629
+ rb_define_method(cBackend, "analytics_link_connect", VALUE_FUNC(cb_Backend_analytics_link_connect), 1);
8630
+ rb_define_method(cBackend, "analytics_link_disconnect", VALUE_FUNC(cb_Backend_analytics_link_disconnect), 1);
8631
+ rb_define_method(cBackend, "analytics_link_create", VALUE_FUNC(cb_Backend_analytics_link_create), 2);
8632
+ rb_define_method(cBackend, "analytics_link_replace", VALUE_FUNC(cb_Backend_analytics_link_replace), 2);
8633
+ rb_define_method(cBackend, "analytics_link_drop", VALUE_FUNC(cb_Backend_analytics_link_drop), 3);
8634
+ rb_define_method(cBackend, "analytics_link_get_all", VALUE_FUNC(cb_Backend_analytics_link_get_all), 1);
7784
8635
 
7785
8636
  rb_define_method(cBackend, "view_index_get_all", VALUE_FUNC(cb_Backend_view_index_get_all), 3);
7786
8637
  rb_define_method(cBackend, "view_index_get", VALUE_FUNC(cb_Backend_view_index_get), 4);
@@ -7797,6 +8648,9 @@ init_backend(VALUE mCouchbase)
7797
8648
  rb_define_singleton_method(cBackend, "snappy_uncompress", VALUE_FUNC(cb_Backend_snappy_uncompress), 1);
7798
8649
  rb_define_singleton_method(cBackend, "leb128_encode", VALUE_FUNC(cb_Backend_leb128_encode), 1);
7799
8650
  rb_define_singleton_method(cBackend, "leb128_decode", VALUE_FUNC(cb_Backend_leb128_decode), 1);
8651
+ rb_define_singleton_method(cBackend, "query_escape", VALUE_FUNC(cb_Backend_query_escape), 1);
8652
+ rb_define_singleton_method(cBackend, "path_escape", VALUE_FUNC(cb_Backend_path_escape), 1);
8653
+ rb_define_singleton_method(cBackend, "form_encode", VALUE_FUNC(cb_Backend_form_encode), 1);
7800
8654
  }
7801
8655
 
7802
8656
  void