couchbase 3.4.0 → 3.4.1

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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/couchbase/CMakeLists.txt +8 -3
  4. data/ext/couchbase/cmake/CompilerWarnings.cmake +12 -4
  5. data/ext/couchbase/cmake/Documentation.cmake +4 -3
  6. data/ext/couchbase/cmake/OpenSSL.cmake +52 -7
  7. data/ext/couchbase/cmake/VersionInfo.cmake +39 -3
  8. data/ext/couchbase/cmake/test_openssl.cxx +7 -0
  9. data/ext/couchbase/core/crypto/CMakeLists.txt +5 -1
  10. data/ext/couchbase/core/impl/collection_query_index_manager.cxx +3 -3
  11. data/ext/couchbase/core/impl/get_all_query_indexes.cxx +3 -3
  12. data/ext/couchbase/core/impl/transaction_get_result.cxx +54 -0
  13. data/ext/couchbase/core/meta/CMakeLists.txt +7 -5
  14. data/ext/couchbase/core/meta/version.cxx +19 -0
  15. data/ext/couchbase/core/operations/document_search.cxx +5 -2
  16. data/ext/couchbase/core/operations/document_search.hxx +0 -1
  17. data/ext/couchbase/core/transactions/atr_cleanup_entry.cxx +1 -0
  18. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +62 -31
  19. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +43 -22
  20. data/ext/couchbase/core/transactions/forward_compat.hxx +2 -2
  21. data/ext/couchbase/core/transactions/internal/transaction_context.hxx +1 -1
  22. data/ext/couchbase/core/transactions/internal/transaction_fields.hxx +1 -0
  23. data/ext/couchbase/core/transactions/staged_mutation.cxx +1 -1
  24. data/ext/couchbase/core/transactions/staged_mutation.hxx +12 -2
  25. data/ext/couchbase/core/transactions/transaction_context.cxx +8 -11
  26. data/ext/couchbase/core/transactions/transaction_get_result.cxx +41 -31
  27. data/ext/couchbase/core/transactions/transaction_get_result.hxx +7 -3
  28. data/ext/couchbase/core/transactions/transaction_links.hxx +13 -1
  29. data/ext/couchbase/core/transactions/waitable_op_list.hxx +1 -0
  30. data/ext/couchbase/couchbase/cluster.hxx +2 -2
  31. data/ext/couchbase/couchbase/cluster_options.hxx +10 -10
  32. data/ext/couchbase/couchbase/collection.hxx +22 -17
  33. data/ext/couchbase/couchbase/collection_query_index_manager.hxx +1 -1
  34. data/ext/couchbase/couchbase/common_options.hxx +1 -1
  35. data/ext/couchbase/couchbase/configuration_profile.hxx +1 -1
  36. data/ext/couchbase/couchbase/configuration_profiles_registry.hxx +0 -1
  37. data/ext/couchbase/couchbase/create_primary_query_index_options.hxx +1 -1
  38. data/ext/couchbase/couchbase/drop_primary_query_index_options.hxx +1 -1
  39. data/ext/couchbase/couchbase/drop_query_index_options.hxx +1 -1
  40. data/ext/couchbase/couchbase/fmt/cas.hxx +12 -0
  41. data/ext/couchbase/couchbase/fmt/durability_level.hxx +6 -0
  42. data/ext/couchbase/couchbase/fmt/key_value_extended_error_info.hxx +6 -0
  43. data/ext/couchbase/couchbase/fmt/key_value_status_code.hxx +6 -0
  44. data/ext/couchbase/couchbase/fmt/mutation_token.hxx +6 -0
  45. data/ext/couchbase/couchbase/fmt/query_scan_consistency.hxx +6 -0
  46. data/ext/couchbase/couchbase/fmt/query_status.hxx +6 -0
  47. data/ext/couchbase/couchbase/fmt/retry_reason.hxx +6 -0
  48. data/ext/couchbase/couchbase/fmt/tls_verify_mode.hxx +6 -0
  49. data/ext/couchbase/couchbase/get_all_query_indexes_options.hxx +5 -4
  50. data/ext/couchbase/couchbase/query_index_manager.hxx +4 -2
  51. data/ext/couchbase/couchbase/scope.hxx +1 -1
  52. data/ext/couchbase/couchbase/subdoc/array_add_unique.hxx +2 -0
  53. data/ext/couchbase/couchbase/subdoc/array_append.hxx +2 -0
  54. data/ext/couchbase/couchbase/subdoc/array_insert.hxx +2 -0
  55. data/ext/couchbase/couchbase/subdoc/array_prepend.hxx +2 -0
  56. data/ext/couchbase/couchbase/subdoc/count.hxx +2 -0
  57. data/ext/couchbase/couchbase/subdoc/counter.hxx +2 -0
  58. data/ext/couchbase/couchbase/subdoc/exists.hxx +2 -0
  59. data/ext/couchbase/couchbase/subdoc/get.hxx +2 -0
  60. data/ext/couchbase/couchbase/subdoc/insert.hxx +2 -0
  61. data/ext/couchbase/couchbase/subdoc/remove.hxx +2 -0
  62. data/ext/couchbase/couchbase/subdoc/replace.hxx +3 -1
  63. data/ext/couchbase/couchbase/subdoc/upsert.hxx +2 -0
  64. data/ext/couchbase/couchbase/transaction_op_error_context.hxx +4 -4
  65. data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +36 -51
  66. data/ext/couchbase/couchbase/transactions/transactions_config.hxx +1 -1
  67. data/ext/couchbase/test/CMakeLists.txt +2 -0
  68. data/ext/couchbase/test/test_integration_examples.cxx +141 -0
  69. data/ext/couchbase/test/test_unit_transaction_utils.cxx +76 -19
  70. data/ext/couchbase.cxx +479 -20
  71. data/ext/extconf.rb +2 -1
  72. data/ext/revisions.rb +3 -2
  73. data/lib/couchbase/binary_collection.rb +4 -4
  74. data/lib/couchbase/collection.rb +5 -0
  75. data/lib/couchbase/errors.rb +10 -0
  76. data/lib/couchbase/management/collection_query_index_manager.rb +183 -0
  77. data/lib/couchbase/management/query_index_manager.rb +35 -3
  78. data/lib/couchbase/management.rb +1 -0
  79. data/lib/couchbase/options.rb +2 -3
  80. data/lib/couchbase/version.rb +1 -1
  81. metadata +9 -5
@@ -225,37 +225,94 @@ TEST_CASE("transaction_get_result: can convert core transaction_get_result to pu
225
225
  const std::string collection = "collection";
226
226
  const std::string key = "key";
227
227
  const couchbase::cas cas(100ULL);
228
+ const auto fwd_compat = tao::json::value::array({ "xxx", "yyy" });
229
+ const couchbase::core::transactions::transaction_links links("atr_id",
230
+ "atr_bucket",
231
+ "atr_scope",
232
+ "atr_collection",
233
+ "txn_id",
234
+ "attempt_id",
235
+ "op_id",
236
+ binary_content,
237
+ "cas_pre_txn",
238
+ "rev_pre_txn",
239
+ 0,
240
+ "crc",
241
+ "op",
242
+ fwd_compat,
243
+ false);
244
+ const couchbase::core::transactions::document_metadata metadata("cas", "revid", 0, "crc32");
228
245
 
229
- SECTION("public to core")
230
- {
231
- couchbase::transactions::transaction_get_result public_result(bucket, scope, collection, key, cas, binary_content);
232
- couchbase::core::transactions::transaction_get_result core_result(public_result);
233
- REQUIRE(core_result.collection() == collection);
234
- REQUIRE(core_result.bucket() == bucket);
235
- REQUIRE(core_result.scope() == scope);
236
- REQUIRE(core_result.cas() == cas);
237
- REQUIRE(core_result.content() == binary_content);
238
- REQUIRE(public_result.collection() == collection);
239
- REQUIRE(public_result.bucket() == bucket);
240
- REQUIRE(public_result.scope() == scope);
241
- REQUIRE(public_result.cas() == cas);
242
- REQUIRE(public_result.content() == binary_content);
243
- }
244
- SECTION("core to public")
246
+ SECTION("core->public")
245
247
  {
246
248
  couchbase::core::transactions::transaction_get_result core_result(
247
- { bucket, scope, collection, key }, binary_content, cas.value(), {}, {});
249
+ { bucket, scope, collection, key }, binary_content, cas.value(), links, metadata);
248
250
  auto public_result = core_result.to_public_result();
249
251
  REQUIRE(public_result.collection() == collection);
250
252
  REQUIRE(public_result.bucket() == bucket);
251
253
  REQUIRE(public_result.scope() == scope);
252
254
  REQUIRE(public_result.cas() == cas);
255
+ REQUIRE(public_result.key() == key);
253
256
  REQUIRE(public_result.content() == binary_content);
257
+ REQUIRE(public_result.content<tao::json::value>() == content);
254
258
  REQUIRE(core_result.collection() == collection);
255
259
  REQUIRE(core_result.bucket() == bucket);
256
260
  REQUIRE(core_result.scope() == scope);
257
261
  REQUIRE(core_result.cas() == cas);
258
- // the content is _moved_ when creating the public_result
259
- REQUIRE(core_result.content().empty());
262
+ REQUIRE(core_result.key() == key);
263
+ // the content is _moved_ when creating the public_result, so lets not touch the
264
+ // core_result.content() since it can be anything. The std::vector is _valid_, so we
265
+ // can manipulate it, but the contents are not guaranteed.
266
+ }
267
+ SECTION("core->public->core")
268
+ {
269
+ couchbase::core::transactions::transaction_get_result core_result(
270
+ { bucket, scope, collection, key }, binary_content, cas.value(), links, metadata);
271
+ auto public_result = core_result.to_public_result();
272
+ couchbase::core::transactions::transaction_get_result final_core_result(public_result);
273
+ REQUIRE(core_result.collection() == final_core_result.collection());
274
+ REQUIRE(core_result.bucket() == final_core_result.bucket());
275
+ REQUIRE(core_result.scope() == final_core_result.scope());
276
+ REQUIRE(core_result.cas() == final_core_result.cas());
277
+ REQUIRE(final_core_result.content() == binary_content);
278
+ REQUIRE(core_result.key() == final_core_result.key());
279
+ REQUIRE(final_core_result.cas() == cas);
280
+ REQUIRE(final_core_result.bucket() == bucket);
281
+ REQUIRE(final_core_result.scope() == scope);
282
+ REQUIRE(final_core_result.collection() == collection);
283
+ REQUIRE(final_core_result.key() == key);
284
+ REQUIRE(final_core_result.content() == binary_content);
285
+ REQUIRE(final_core_result.links().staged_operation_id() == links.staged_operation_id());
286
+ REQUIRE(final_core_result.links().staged_attempt_id() == links.staged_attempt_id());
287
+ REQUIRE(final_core_result.links().crc32_of_staging() == links.crc32_of_staging());
288
+ REQUIRE(final_core_result.links().atr_collection_name() == links.atr_collection_name());
289
+ REQUIRE(final_core_result.links().atr_scope_name() == links.atr_scope_name());
290
+ REQUIRE(final_core_result.links().atr_bucket_name() == links.atr_bucket_name());
291
+ REQUIRE(final_core_result.links().is_deleted() == links.is_deleted());
292
+ REQUIRE(final_core_result.links().forward_compat() == links.forward_compat());
293
+ REQUIRE(final_core_result.links().atr_id() == links.atr_id());
294
+ REQUIRE(final_core_result.links().cas_pre_txn() == links.cas_pre_txn());
295
+ REQUIRE(final_core_result.links().exptime_pre_txn() == links.exptime_pre_txn());
296
+ REQUIRE(final_core_result.links().op() == links.op());
297
+ REQUIRE(final_core_result.links().revid_pre_txn() == links.revid_pre_txn());
298
+ REQUIRE(final_core_result.links().staged_content() == links.staged_content());
299
+ REQUIRE(final_core_result.links().staged_transaction_id() == links.staged_transaction_id());
300
+ REQUIRE(final_core_result.metadata()->cas() == metadata.cas());
301
+ REQUIRE(final_core_result.metadata()->crc32() == metadata.crc32());
302
+ REQUIRE(final_core_result.metadata()->exptime() == metadata.exptime());
303
+ REQUIRE(final_core_result.metadata()->revid() == metadata.revid());
304
+ }
305
+ SECTION("default constructed core->public")
306
+ {
307
+ couchbase::core::transactions::transaction_get_result core_result{};
308
+ auto final_public_result = core_result.to_public_result();
309
+ REQUIRE(final_public_result.cas().empty());
310
+ }
311
+ SECTION("default constructed public->core->public")
312
+ {
313
+ couchbase::transactions::transaction_get_result public_res;
314
+ couchbase::core::transactions::transaction_get_result core_res(public_res);
315
+ auto final_public_res = core_res.to_public_result();
316
+ REQUIRE(final_public_res.cas().empty());
260
317
  }
261
318
  }
data/ext/couchbase.cxx CHANGED
@@ -5084,9 +5084,9 @@ cb_Backend_query_index_get_all(VALUE self, VALUE bucket_name, VALUE options)
5084
5084
  VALUE indexes = rb_ary_new_capa(static_cast<long>(resp.indexes.size()));
5085
5085
  for (const auto& idx : resp.indexes) {
5086
5086
  VALUE index = rb_hash_new();
5087
- rb_hash_aset(index, rb_id2sym(rb_intern("state")), cb_str_new(idx.state));
5087
+ rb_hash_aset(index, rb_id2sym(rb_intern("state")), rb_id2sym(rb_intern(idx.state.c_str())));
5088
5088
  rb_hash_aset(index, rb_id2sym(rb_intern("name")), cb_str_new(idx.name));
5089
- rb_hash_aset(index, rb_id2sym(rb_intern("type")), cb_str_new(idx.type));
5089
+ rb_hash_aset(index, rb_id2sym(rb_intern("type")), rb_id2sym(rb_intern(idx.type.c_str())));
5090
5090
  rb_hash_aset(index, rb_id2sym(rb_intern("is_primary")), idx.is_primary ? Qtrue : Qfalse);
5091
5091
  VALUE index_key = rb_ary_new_capa(static_cast<long>(idx.index_key.size()));
5092
5092
  for (const auto& key : idx.index_key) {
@@ -5463,16 +5463,473 @@ cb_Backend_query_index_build_deferred(VALUE self, VALUE bucket_name, VALUE optio
5463
5463
  }
5464
5464
 
5465
5465
  static VALUE
5466
- cb_Backend_query_index_watch(VALUE /* self */, VALUE bucket_name, VALUE index_names, VALUE timeout, VALUE options)
5466
+ cb_Backend_collection_query_index_get_all(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE options)
5467
5467
  {
5468
+ const auto& cluster = cb_backend_to_cluster(self);
5469
+
5468
5470
  Check_Type(bucket_name, T_STRING);
5469
- Check_Type(index_names, T_ARRAY);
5470
- Check_Type(timeout, T_FIXNUM);
5471
+ Check_Type(scope_name, T_STRING);
5472
+ Check_Type(collection_name, T_STRING);
5471
5473
  if (!NIL_P(options)) {
5472
5474
  Check_Type(options, T_HASH);
5473
5475
  }
5474
5476
 
5475
- return Qtrue;
5477
+ try {
5478
+ couchbase::core::operations::management::query_index_get_all_request req{};
5479
+ req.bucket_name = cb_string_new(bucket_name);
5480
+ req.scope_name = cb_string_new(scope_name);
5481
+ req.collection_name = cb_string_new(collection_name);
5482
+ cb_extract_timeout(req, options);
5483
+ auto barrier = std::make_shared<std::promise<couchbase::core::operations::management::query_index_get_all_response>>();
5484
+ auto f = barrier->get_future();
5485
+ cluster->execute(req, [barrier](couchbase::core::operations::management::query_index_get_all_response&& resp) {
5486
+ barrier->set_value(std::move(resp));
5487
+ });
5488
+ auto resp = cb_wait_for_future(f);
5489
+ if (resp.ctx.ec) {
5490
+ cb_throw_error_code(resp.ctx, fmt::format("unable to get list of the indexes of the collection \"{}\"", req.collection_name));
5491
+ }
5492
+
5493
+ VALUE res = rb_hash_new();
5494
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), cb_str_new(resp.status));
5495
+ VALUE indexes = rb_ary_new_capa(static_cast<long>(resp.indexes.size()));
5496
+ for (const auto& idx : resp.indexes) {
5497
+ VALUE index = rb_hash_new();
5498
+ rb_hash_aset(index, rb_id2sym(rb_intern("state")), rb_id2sym(rb_intern(idx.state.c_str())));
5499
+ rb_hash_aset(index, rb_id2sym(rb_intern("name")), cb_str_new(idx.name));
5500
+ rb_hash_aset(index, rb_id2sym(rb_intern("type")), rb_id2sym(rb_intern(idx.type.c_str())));
5501
+ rb_hash_aset(index, rb_id2sym(rb_intern("is_primary")), idx.is_primary ? Qtrue : Qfalse);
5502
+ VALUE index_key = rb_ary_new_capa(static_cast<long>(idx.index_key.size()));
5503
+ for (const auto& key : idx.index_key) {
5504
+ rb_ary_push(index_key, cb_str_new(key));
5505
+ }
5506
+ rb_hash_aset(index, rb_id2sym(rb_intern("index_key")), index_key);
5507
+ if (idx.collection_name) {
5508
+ rb_hash_aset(index, rb_id2sym(rb_intern("collection_name")), cb_str_new(idx.collection_name.value()));
5509
+ }
5510
+ if (idx.scope_name) {
5511
+ rb_hash_aset(index, rb_id2sym(rb_intern("scope_name")), cb_str_new(idx.scope_name.value()));
5512
+ }
5513
+ rb_hash_aset(index, rb_id2sym(rb_intern("bucket_name")), cb_str_new(idx.bucket_name));
5514
+ if (idx.condition) {
5515
+ rb_hash_aset(index, rb_id2sym(rb_intern("condition")), cb_str_new(idx.condition.value()));
5516
+ }
5517
+ if (idx.partition) {
5518
+ rb_hash_aset(index, rb_id2sym(rb_intern("partition")), cb_str_new(idx.partition.value()));
5519
+ }
5520
+ rb_ary_push(indexes, index);
5521
+ }
5522
+
5523
+ rb_hash_aset(res, rb_id2sym(rb_intern("indexes")), indexes);
5524
+
5525
+ return res;
5526
+ } catch (const std::system_error& se) {
5527
+ rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
5528
+ } catch (const ruby_exception& e) {
5529
+ rb_exc_raise(e.exception_object());
5530
+ }
5531
+ return Qnil;
5532
+ }
5533
+
5534
+ static VALUE
5535
+ cb_Backend_collection_query_index_create(VALUE self,
5536
+ VALUE bucket_name,
5537
+ VALUE scope_name,
5538
+ VALUE collection_name,
5539
+ VALUE index_name,
5540
+ VALUE fields,
5541
+ VALUE options)
5542
+ {
5543
+ const auto& cluster = cb_backend_to_cluster(self);
5544
+
5545
+ Check_Type(bucket_name, T_STRING);
5546
+ Check_Type(scope_name, T_STRING);
5547
+ Check_Type(collection_name, T_STRING);
5548
+ Check_Type(index_name, T_STRING);
5549
+ Check_Type(fields, T_ARRAY);
5550
+ if (!NIL_P(options)) {
5551
+ Check_Type(options, T_HASH);
5552
+ }
5553
+
5554
+ try {
5555
+ couchbase::core::operations::management::query_index_create_request req{};
5556
+ cb_extract_timeout(req, options);
5557
+ req.bucket_name = cb_string_new(bucket_name);
5558
+ req.scope_name = cb_string_new(scope_name);
5559
+ req.collection_name = cb_string_new(collection_name);
5560
+ req.index_name = cb_string_new(index_name);
5561
+ auto fields_num = static_cast<std::size_t>(RARRAY_LEN(fields));
5562
+ req.fields.reserve(fields_num);
5563
+ for (std::size_t i = 0; i < fields_num; ++i) {
5564
+ VALUE entry = rb_ary_entry(fields, static_cast<long>(i));
5565
+ cb_check_type(entry, T_STRING);
5566
+ req.fields.emplace_back(RSTRING_PTR(entry), static_cast<std::size_t>(RSTRING_LEN(entry)));
5567
+ }
5568
+ if (!NIL_P(options)) {
5569
+ if (VALUE ignore_if_exists = rb_hash_aref(options, rb_id2sym(rb_intern("ignore_if_exists"))); ignore_if_exists == Qtrue) {
5570
+ req.ignore_if_exists = true;
5571
+ } else if (ignore_if_exists == Qfalse) {
5572
+ req.ignore_if_exists = false;
5573
+ } /* else use backend default */
5574
+ if (VALUE deferred = rb_hash_aref(options, rb_id2sym(rb_intern("deferred"))); deferred == Qtrue) {
5575
+ req.deferred = true;
5576
+ } else if (deferred == Qfalse) {
5577
+ req.deferred = false;
5578
+ } /* else use backend default */
5579
+ if (VALUE num_replicas = rb_hash_aref(options, rb_id2sym(rb_intern("num_replicas"))); !NIL_P(num_replicas)) {
5580
+ req.num_replicas = NUM2UINT(num_replicas);
5581
+ } /* else use backend default */
5582
+ if (VALUE condition = rb_hash_aref(options, rb_id2sym(rb_intern("condition"))); !NIL_P(condition)) {
5583
+ req.condition.emplace(cb_string_new(condition));
5584
+ } /* else use backend default */
5585
+ if (VALUE scope_name = rb_hash_aref(options, rb_id2sym(rb_intern("scope_name"))); TYPE(scope_name) == T_STRING) {
5586
+ req.scope_name = cb_string_new(scope_name);
5587
+ }
5588
+ if (VALUE collection_name = rb_hash_aref(options, rb_id2sym(rb_intern("collection_name"))); TYPE(collection_name) == T_STRING) {
5589
+ req.collection_name = cb_string_new(collection_name);
5590
+ }
5591
+ }
5592
+
5593
+ auto barrier = std::make_shared<std::promise<couchbase::core::operations::management::query_index_create_response>>();
5594
+ auto f = barrier->get_future();
5595
+ cluster->execute(req, [barrier](couchbase::core::operations::management::query_index_create_response&& resp) {
5596
+ barrier->set_value(std::move(resp));
5597
+ });
5598
+ auto resp = cb_wait_for_future(f);
5599
+ if (resp.ctx.ec) {
5600
+ if (!resp.errors.empty()) {
5601
+ const auto& first_error = resp.errors.front();
5602
+ cb_throw_error_code(resp.ctx,
5603
+ fmt::format(R"(unable to create index "{}" on the collection "{}" ({}: {}))",
5604
+ req.index_name,
5605
+ req.collection_name,
5606
+ first_error.code,
5607
+ first_error.message));
5608
+ } else {
5609
+ cb_throw_error_code(
5610
+ resp.ctx, fmt::format(R"(unable to create index "{}" on the collection "{}")", req.index_name, req.collection_name));
5611
+ }
5612
+ }
5613
+ VALUE res = rb_hash_new();
5614
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), cb_str_new(resp.status));
5615
+ if (!resp.errors.empty()) {
5616
+ VALUE errors = rb_ary_new_capa(static_cast<long>(resp.errors.size()));
5617
+ for (const auto& err : resp.errors) {
5618
+ VALUE error = rb_hash_new();
5619
+ rb_hash_aset(error, rb_id2sym(rb_intern("code")), ULL2NUM(err.code));
5620
+ rb_hash_aset(error, rb_id2sym(rb_intern("message")), cb_str_new(err.message));
5621
+ rb_ary_push(errors, error);
5622
+ }
5623
+ rb_hash_aset(res, rb_id2sym(rb_intern("errors")), errors);
5624
+ }
5625
+ return res;
5626
+ } catch (const std::system_error& se) {
5627
+ rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
5628
+ } catch (const ruby_exception& e) {
5629
+ rb_exc_raise(e.exception_object());
5630
+ }
5631
+ return Qnil;
5632
+ }
5633
+
5634
+ static VALUE
5635
+ cb_Backend_collection_query_index_drop(VALUE self,
5636
+ VALUE bucket_name,
5637
+ VALUE scope_name,
5638
+ VALUE collection_name,
5639
+ VALUE index_name,
5640
+ VALUE options)
5641
+ {
5642
+ const auto& cluster = cb_backend_to_cluster(self);
5643
+
5644
+ Check_Type(bucket_name, T_STRING);
5645
+ Check_Type(scope_name, T_STRING);
5646
+ Check_Type(collection_name, T_STRING);
5647
+ Check_Type(index_name, T_STRING);
5648
+ if (!NIL_P(options)) {
5649
+ Check_Type(options, T_HASH);
5650
+ }
5651
+
5652
+ try {
5653
+ couchbase::core::operations::management::query_index_drop_request req{};
5654
+ cb_extract_timeout(req, options);
5655
+ req.bucket_name = cb_string_new(bucket_name);
5656
+ req.scope_name = cb_string_new(scope_name);
5657
+ req.collection_name = cb_string_new(collection_name);
5658
+ req.index_name = cb_string_new(index_name);
5659
+ if (!NIL_P(options)) {
5660
+ if (VALUE ignore_if_does_not_exist = rb_hash_aref(options, rb_id2sym(rb_intern("ignore_if_does_not_exist")));
5661
+ ignore_if_does_not_exist == Qtrue) {
5662
+ req.ignore_if_does_not_exist = true;
5663
+ } else if (ignore_if_does_not_exist == Qfalse) {
5664
+ req.ignore_if_does_not_exist = false;
5665
+ } /* else use backend default */
5666
+ if (VALUE scope_name = rb_hash_aref(options, rb_id2sym(rb_intern("scope_name"))); TYPE(scope_name) == T_STRING) {
5667
+ req.scope_name = cb_string_new(scope_name);
5668
+ }
5669
+ if (VALUE collection_name = rb_hash_aref(options, rb_id2sym(rb_intern("collection_name"))); TYPE(collection_name) == T_STRING) {
5670
+ req.collection_name = cb_string_new(collection_name);
5671
+ }
5672
+ }
5673
+
5674
+ auto barrier = std::make_shared<std::promise<couchbase::core::operations::management::query_index_drop_response>>();
5675
+ auto f = barrier->get_future();
5676
+ cluster->execute(req, [barrier](couchbase::core::operations::management::query_index_drop_response&& resp) {
5677
+ barrier->set_value(std::move(resp));
5678
+ });
5679
+ auto resp = cb_wait_for_future(f);
5680
+ if (resp.ctx.ec) {
5681
+ if (!resp.errors.empty()) {
5682
+ const auto& first_error = resp.errors.front();
5683
+ cb_throw_error_code(resp.ctx,
5684
+ fmt::format(R"(unable to drop index "{}" on the collection "{}" ({}: {}))",
5685
+ req.index_name,
5686
+ req.collection_name,
5687
+ first_error.code,
5688
+ first_error.message));
5689
+ } else {
5690
+ cb_throw_error_code(
5691
+ resp.ctx, fmt::format(R"(unable to drop index "{}" on the collection "{}")", req.index_name, req.collection_name));
5692
+ }
5693
+ }
5694
+ VALUE res = rb_hash_new();
5695
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), cb_str_new(resp.status));
5696
+ if (!resp.errors.empty()) {
5697
+ VALUE errors = rb_ary_new_capa(static_cast<long>(resp.errors.size()));
5698
+ for (const auto& err : resp.errors) {
5699
+ VALUE error = rb_hash_new();
5700
+ rb_hash_aset(error, rb_id2sym(rb_intern("code")), ULL2NUM(err.code));
5701
+ rb_hash_aset(error, rb_id2sym(rb_intern("message")), cb_str_new(err.message));
5702
+ rb_ary_push(errors, error);
5703
+ }
5704
+ rb_hash_aset(res, rb_id2sym(rb_intern("errors")), errors);
5705
+ }
5706
+ return res;
5707
+ } catch (const std::system_error& se) {
5708
+ rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
5709
+ } catch (const ruby_exception& e) {
5710
+ rb_exc_raise(e.exception_object());
5711
+ }
5712
+ return Qnil;
5713
+ }
5714
+
5715
+ static VALUE
5716
+ cb_Backend_collection_query_index_create_primary(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE options)
5717
+ {
5718
+ const auto& cluster = cb_backend_to_cluster(self);
5719
+
5720
+ Check_Type(bucket_name, T_STRING);
5721
+ Check_Type(scope_name, T_STRING);
5722
+ Check_Type(collection_name, T_STRING);
5723
+ if (!NIL_P(options)) {
5724
+ Check_Type(options, T_HASH);
5725
+ }
5726
+
5727
+ try {
5728
+ couchbase::core::operations::management::query_index_create_request req{};
5729
+ cb_extract_timeout(req, options);
5730
+ req.is_primary = true;
5731
+ req.bucket_name = cb_string_new(bucket_name);
5732
+ req.scope_name = cb_string_new(scope_name);
5733
+ req.collection_name = cb_string_new(collection_name);
5734
+ if (!NIL_P(options)) {
5735
+ if (VALUE ignore_if_exists = rb_hash_aref(options, rb_id2sym(rb_intern("ignore_if_exists"))); ignore_if_exists == Qtrue) {
5736
+ req.ignore_if_exists = true;
5737
+ } else if (ignore_if_exists == Qfalse) {
5738
+ req.ignore_if_exists = false;
5739
+ } /* else use backend default */
5740
+ if (VALUE deferred = rb_hash_aref(options, rb_id2sym(rb_intern("deferred"))); deferred == Qtrue) {
5741
+ req.deferred = true;
5742
+ } else if (deferred == Qfalse) {
5743
+ req.deferred = false;
5744
+ } /* else use backend default */
5745
+ if (VALUE num_replicas = rb_hash_aref(options, rb_id2sym(rb_intern("num_replicas"))); !NIL_P(num_replicas)) {
5746
+ req.num_replicas = NUM2UINT(num_replicas);
5747
+ } /* else use backend default */
5748
+ if (VALUE index_name = rb_hash_aref(options, rb_id2sym(rb_intern("index_name"))); TYPE(index_name) == T_STRING) {
5749
+ req.index_name = cb_string_new(index_name);
5750
+ } /* else use backend default */
5751
+ if (VALUE scope_name = rb_hash_aref(options, rb_id2sym(rb_intern("scope_name"))); TYPE(scope_name) == T_STRING) {
5752
+ req.scope_name = cb_string_new(scope_name);
5753
+ }
5754
+ if (VALUE collection_name = rb_hash_aref(options, rb_id2sym(rb_intern("collection_name"))); TYPE(collection_name) == T_STRING) {
5755
+ req.collection_name = cb_string_new(collection_name);
5756
+ }
5757
+ }
5758
+
5759
+ auto barrier = std::make_shared<std::promise<couchbase::core::operations::management::query_index_create_response>>();
5760
+ auto f = barrier->get_future();
5761
+ cluster->execute(req, [barrier](couchbase::core::operations::management::query_index_create_response&& resp) {
5762
+ barrier->set_value(std::move(resp));
5763
+ });
5764
+ auto resp = cb_wait_for_future(f);
5765
+ if (resp.ctx.ec) {
5766
+ if (!resp.errors.empty()) {
5767
+ const auto& first_error = resp.errors.front();
5768
+ cb_throw_error_code(resp.ctx,
5769
+ fmt::format(R"(unable to create primary index on the collection "{}" ({}: {}))",
5770
+ req.collection_name,
5771
+ first_error.code,
5772
+ first_error.message));
5773
+ } else {
5774
+ cb_throw_error_code(resp.ctx, fmt::format(R"(unable to create primary index on the collection "{}")", req.collection_name));
5775
+ }
5776
+ }
5777
+ VALUE res = rb_hash_new();
5778
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), cb_str_new(resp.status));
5779
+ if (!resp.errors.empty()) {
5780
+ VALUE errors = rb_ary_new_capa(static_cast<long>(resp.errors.size()));
5781
+ for (const auto& err : resp.errors) {
5782
+ VALUE error = rb_hash_new();
5783
+ rb_hash_aset(error, rb_id2sym(rb_intern("code")), ULL2NUM(err.code));
5784
+ rb_hash_aset(error, rb_id2sym(rb_intern("message")), cb_str_new(err.message));
5785
+ rb_ary_push(errors, error);
5786
+ }
5787
+ rb_hash_aset(res, rb_id2sym(rb_intern("errors")), errors);
5788
+ }
5789
+ return res;
5790
+ } catch (const std::system_error& se) {
5791
+ rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
5792
+ } catch (const ruby_exception& e) {
5793
+ rb_exc_raise(e.exception_object());
5794
+ }
5795
+ return Qnil;
5796
+ }
5797
+
5798
+ static VALUE
5799
+ cb_Backend_collection_query_index_drop_primary(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE options)
5800
+ {
5801
+ const auto& cluster = cb_backend_to_cluster(self);
5802
+
5803
+ Check_Type(bucket_name, T_STRING);
5804
+ Check_Type(scope_name, T_STRING);
5805
+ Check_Type(collection_name, T_STRING);
5806
+ if (!NIL_P(options)) {
5807
+ Check_Type(options, T_HASH);
5808
+ }
5809
+
5810
+ try {
5811
+ couchbase::core::operations::management::query_index_drop_request req{};
5812
+ cb_extract_timeout(req, options);
5813
+ req.is_primary = true;
5814
+ req.bucket_name = cb_string_new(bucket_name);
5815
+ req.scope_name = cb_string_new(scope_name);
5816
+ req.collection_name = cb_string_new(collection_name);
5817
+ if (!NIL_P(options)) {
5818
+ if (VALUE ignore_if_does_not_exist = rb_hash_aref(options, rb_id2sym(rb_intern("ignore_if_does_not_exist")));
5819
+ ignore_if_does_not_exist == Qtrue) {
5820
+ req.ignore_if_does_not_exist = true;
5821
+ } else if (ignore_if_does_not_exist == Qfalse) {
5822
+ req.ignore_if_does_not_exist = false;
5823
+ } /* else use backend default */
5824
+ if (VALUE index_name = rb_hash_aref(options, rb_id2sym(rb_intern("index_name"))); !NIL_P(index_name)) {
5825
+ cb_check_type(options, T_STRING);
5826
+ req.is_primary = false;
5827
+ req.bucket_name = cb_string_new(index_name);
5828
+ }
5829
+ if (VALUE scope_name = rb_hash_aref(options, rb_id2sym(rb_intern("scope_name"))); TYPE(scope_name) == T_STRING) {
5830
+ req.scope_name = cb_string_new(scope_name);
5831
+ }
5832
+ if (VALUE collection_name = rb_hash_aref(options, rb_id2sym(rb_intern("collection_name"))); TYPE(collection_name) == T_STRING) {
5833
+ req.collection_name = cb_string_new(collection_name);
5834
+ }
5835
+ }
5836
+
5837
+ auto barrier = std::make_shared<std::promise<couchbase::core::operations::management::query_index_drop_response>>();
5838
+ auto f = barrier->get_future();
5839
+ cluster->execute(req, [barrier](couchbase::core::operations::management::query_index_drop_response&& resp) {
5840
+ barrier->set_value(std::move(resp));
5841
+ });
5842
+ auto resp = cb_wait_for_future(f);
5843
+ if (resp.ctx.ec) {
5844
+ if (!resp.errors.empty()) {
5845
+ const auto& first_error = resp.errors.front();
5846
+ cb_throw_error_code(resp.ctx,
5847
+ fmt::format(R"(unable to drop primary index on the collection "{}" ({}: {}))",
5848
+ req.collection_name,
5849
+ first_error.code,
5850
+ first_error.message));
5851
+ } else {
5852
+ cb_throw_error_code(resp.ctx, fmt::format(R"(unable to drop primary index on the collection "{}")", req.collection_name));
5853
+ }
5854
+ }
5855
+ VALUE res = rb_hash_new();
5856
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), cb_str_new(resp.status));
5857
+ if (!resp.errors.empty()) {
5858
+ VALUE errors = rb_ary_new_capa(static_cast<long>(resp.errors.size()));
5859
+ for (const auto& err : resp.errors) {
5860
+ VALUE error = rb_hash_new();
5861
+ rb_hash_aset(error, rb_id2sym(rb_intern("code")), ULL2NUM(err.code));
5862
+ rb_hash_aset(error, rb_id2sym(rb_intern("message")), cb_str_new(err.message));
5863
+ rb_ary_push(errors, error);
5864
+ }
5865
+ rb_hash_aset(res, rb_id2sym(rb_intern("errors")), errors);
5866
+ }
5867
+ return res;
5868
+ } catch (const std::system_error& se) {
5869
+ rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
5870
+ } catch (const ruby_exception& e) {
5871
+ rb_exc_raise(e.exception_object());
5872
+ }
5873
+ return Qnil;
5874
+ }
5875
+
5876
+ static VALUE
5877
+ cb_Backend_collection_query_index_build_deferred(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE options)
5878
+ {
5879
+ const auto& cluster = cb_backend_to_cluster(self);
5880
+
5881
+ Check_Type(bucket_name, T_STRING);
5882
+ Check_Type(scope_name, T_STRING);
5883
+ Check_Type(collection_name, T_STRING);
5884
+ if (!NIL_P(options)) {
5885
+ Check_Type(options, T_HASH);
5886
+ }
5887
+
5888
+ try {
5889
+ couchbase::core::operations::management::query_index_build_deferred_request req{};
5890
+ cb_extract_timeout(req, options);
5891
+ req.bucket_name = cb_string_new(bucket_name);
5892
+ req.scope_name = cb_string_new(scope_name);
5893
+ req.collection_name = cb_string_new(collection_name);
5894
+
5895
+ auto barrier = std::make_shared<std::promise<couchbase::core::operations::management::query_index_build_deferred_response>>();
5896
+ auto f = barrier->get_future();
5897
+ cluster->execute(req, [barrier](couchbase::core::operations::management::query_index_build_deferred_response&& resp) {
5898
+ barrier->set_value(std::move(resp));
5899
+ });
5900
+ auto resp = cb_wait_for_future(f);
5901
+ if (resp.ctx.ec) {
5902
+ if (!resp.errors.empty()) {
5903
+ const auto& first_error = resp.errors.front();
5904
+ cb_throw_error_code(resp.ctx,
5905
+ fmt::format(R"(unable to build deferred indexes on the collection "{}" ({}: {}))",
5906
+ req.collection_name.value(),
5907
+ first_error.code,
5908
+ first_error.message));
5909
+ } else {
5910
+ cb_throw_error_code(resp.ctx,
5911
+ fmt::format(R"(unable to build deferred indexes on the collection "{}")", req.collection_name.value()));
5912
+ }
5913
+ }
5914
+ VALUE res = rb_hash_new();
5915
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), cb_str_new(resp.status));
5916
+ if (!resp.errors.empty()) {
5917
+ VALUE errors = rb_ary_new_capa(static_cast<long>(resp.errors.size()));
5918
+ for (const auto& err : resp.errors) {
5919
+ VALUE error = rb_hash_new();
5920
+ rb_hash_aset(error, rb_id2sym(rb_intern("code")), ULL2NUM(err.code));
5921
+ rb_hash_aset(error, rb_id2sym(rb_intern("message")), cb_str_new(err.message));
5922
+ rb_ary_push(errors, error);
5923
+ }
5924
+ rb_hash_aset(res, rb_id2sym(rb_intern("errors")), errors);
5925
+ }
5926
+ return res;
5927
+ } catch (const std::system_error& se) {
5928
+ rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
5929
+ } catch (const ruby_exception& e) {
5930
+ rb_exc_raise(e.exception_object());
5931
+ }
5932
+ return Qnil;
5476
5933
  }
5477
5934
 
5478
5935
  static void
@@ -6150,19 +6607,15 @@ cb_Backend_document_search(VALUE self, VALUE index_name, VALUE query, VALUE opti
6150
6607
  }
6151
6608
  }
6152
6609
 
6153
- if (VALUE scope_name = rb_hash_aref(options, rb_id2sym(rb_intern("scope_name")));
6154
- !NIL_P(scope_name) && TYPE(scope_name) == T_STRING) {
6155
- req.scope_name.emplace(cb_string_new(scope_name));
6156
- VALUE collections = rb_hash_aref(options, rb_id2sym(rb_intern("collections")));
6157
- if (!NIL_P(collections)) {
6158
- cb_check_type(collections, T_ARRAY);
6159
- auto collections_size = static_cast<std::size_t>(RARRAY_LEN(collections));
6160
- req.collections.reserve(collections_size);
6161
- for (std::size_t i = 0; i < collections_size; ++i) {
6162
- VALUE collection = rb_ary_entry(collections, static_cast<long>(i));
6163
- cb_check_type(collection, T_STRING);
6164
- req.collections.emplace_back(cb_string_new(collection));
6165
- }
6610
+ VALUE collections = rb_hash_aref(options, rb_id2sym(rb_intern("collections")));
6611
+ if (!NIL_P(collections)) {
6612
+ cb_check_type(collections, T_ARRAY);
6613
+ auto collections_size = static_cast<std::size_t>(RARRAY_LEN(collections));
6614
+ req.collections.reserve(collections_size);
6615
+ for (std::size_t i = 0; i < collections_size; ++i) {
6616
+ VALUE collection = rb_ary_entry(collections, static_cast<long>(i));
6617
+ cb_check_type(collection, T_STRING);
6618
+ req.collections.emplace_back(cb_string_new(collection));
6166
6619
  }
6167
6620
  }
6168
6621
 
@@ -8132,7 +8585,13 @@ init_backend(VALUE mCouchbase)
8132
8585
  rb_define_method(cBackend, "query_index_drop", VALUE_FUNC(cb_Backend_query_index_drop), 3);
8133
8586
  rb_define_method(cBackend, "query_index_drop_primary", VALUE_FUNC(cb_Backend_query_index_drop_primary), 2);
8134
8587
  rb_define_method(cBackend, "query_index_build_deferred", VALUE_FUNC(cb_Backend_query_index_build_deferred), 2);
8135
- rb_define_method(cBackend, "query_index_watch", VALUE_FUNC(cb_Backend_query_index_watch), 4);
8588
+
8589
+ rb_define_method(cBackend, "collection_query_index_get_all", VALUE_FUNC(cb_Backend_collection_query_index_get_all), 4);
8590
+ rb_define_method(cBackend, "collection_query_index_create", VALUE_FUNC(cb_Backend_collection_query_index_create), 6);
8591
+ rb_define_method(cBackend, "collection_query_index_create_primary", VALUE_FUNC(cb_Backend_collection_query_index_create_primary), 4);
8592
+ rb_define_method(cBackend, "collection_query_index_drop", VALUE_FUNC(cb_Backend_collection_query_index_drop), 5);
8593
+ rb_define_method(cBackend, "collection_query_index_drop_primary", VALUE_FUNC(cb_Backend_collection_query_index_drop_primary), 4);
8594
+ rb_define_method(cBackend, "collection_query_index_build_deferred", VALUE_FUNC(cb_Backend_collection_query_index_build_deferred), 4);
8136
8595
 
8137
8596
  rb_define_method(cBackend, "search_get_stats", VALUE_FUNC(cb_Backend_search_get_stats), 1);
8138
8597
  rb_define_method(cBackend, "search_index_get_all", VALUE_FUNC(cb_Backend_search_index_get_all), 1);
data/ext/extconf.rb CHANGED
@@ -43,7 +43,7 @@ def sys(*cmd)
43
43
  system(*cmd)
44
44
  end
45
45
 
46
- build_type = ENV["DEBUG"] ? "Debug" : "RelWithDebInfo"
46
+ build_type = ENV["DEBUG"] ? "Debug" : "Release"
47
47
  cmake_flags = [
48
48
  "-DCMAKE_BUILD_TYPE=#{build_type}",
49
49
  "-DRUBY_HDR_DIR=#{RbConfig::CONFIG['rubyhdrdir']}",
@@ -74,6 +74,7 @@ case RbConfig::CONFIG["target_os"]
74
74
  when /darwin/
75
75
  openssl_root = `brew --prefix openssl@1.1 2> /dev/null`.strip
76
76
  openssl_root = `brew --prefix openssl@3 2> /dev/null`.strip if openssl_root.empty?
77
+ openssl_root = `brew --prefix openssl 2> /dev/null`.strip if openssl_root.empty?
77
78
  cmake_flags << "-DOPENSSL_ROOT_DIR=#{openssl_root}" unless openssl_root.empty?
78
79
  when /linux/
79
80
  openssl_root = ["/usr/lib64/openssl11", "/usr/include/openssl11"]