couchbase 3.4.0 → 3.4.1

Sign up to get free protection for your applications and to get access to all the features.
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"]