couchbase 4.2.1 → 4.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. package/CMakeLists.txt +1 -0
  2. package/deps/couchbase-cxx-client/.gitmodules +3 -0
  3. package/deps/couchbase-cxx-client/.idea/misc.xml +1 -0
  4. package/deps/couchbase-cxx-client/.idea/vcs.xml +1 -0
  5. package/deps/couchbase-cxx-client/CMakeLists.txt +11 -1
  6. package/deps/couchbase-cxx-client/README.md +3 -3
  7. package/deps/couchbase-cxx-client/cmake/CompilerWarnings.cmake +4 -1
  8. package/deps/couchbase-cxx-client/cmake/VersionInfo.cmake +13 -1
  9. package/deps/couchbase-cxx-client/cmake/build_version.hxx.in +1 -0
  10. package/deps/couchbase-cxx-client/core/cluster.hxx +15 -5
  11. package/deps/couchbase-cxx-client/core/impl/build_deferred_query_indexes.cxx +17 -6
  12. package/deps/couchbase-cxx-client/core/impl/cluster.cxx +1 -1
  13. package/deps/couchbase-cxx-client/core/impl/collection_query_index_manager.cxx +93 -0
  14. package/deps/couchbase-cxx-client/core/impl/configuration_profiles_registry.cxx +11 -0
  15. package/deps/couchbase-cxx-client/core/impl/create_query_index.cxx +119 -0
  16. package/deps/couchbase-cxx-client/core/impl/drop_query_index.cxx +108 -0
  17. package/deps/couchbase-cxx-client/core/impl/get.cxx +1 -1
  18. package/deps/couchbase-cxx-client/core/impl/get_all_query_indexes.cxx +76 -0
  19. package/deps/couchbase-cxx-client/core/impl/query.cxx +5 -7
  20. package/deps/couchbase-cxx-client/core/impl/watch_query_indexes.cxx +168 -0
  21. package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +15 -1
  22. package/deps/couchbase-cxx-client/core/logger/configuration.hxx +3 -0
  23. package/deps/couchbase-cxx-client/core/logger/level.hxx +21 -0
  24. package/deps/couchbase-cxx-client/core/logger/logger.hxx +4 -6
  25. package/deps/couchbase-cxx-client/core/meta/CMakeLists.txt +4 -2
  26. package/deps/couchbase-cxx-client/core/meta/features.hxx +31 -0
  27. package/deps/couchbase-cxx-client/core/meta/version.cxx +67 -5
  28. package/deps/couchbase-cxx-client/core/meta/version.hxx +12 -1
  29. package/deps/couchbase-cxx-client/core/metrics/CMakeLists.txt +4 -1
  30. package/deps/couchbase-cxx-client/core/metrics/logging_meter.cxx +46 -5
  31. package/deps/couchbase-cxx-client/core/metrics/logging_meter.hxx +10 -26
  32. package/deps/couchbase-cxx-client/core/operations/document_get_projected.cxx +3 -2
  33. package/deps/couchbase-cxx-client/core/operations/document_query.cxx +10 -12
  34. package/deps/couchbase-cxx-client/core/operations/document_query.hxx +1 -3
  35. package/deps/couchbase-cxx-client/core/operations/management/query_index_build.cxx +8 -14
  36. package/deps/couchbase-cxx-client/core/operations/management/query_index_build.hxx +2 -1
  37. package/deps/couchbase-cxx-client/core/operations/management/query_index_build_deferred.hxx +15 -8
  38. package/deps/couchbase-cxx-client/core/operations/management/query_index_create.cxx +7 -14
  39. package/deps/couchbase-cxx-client/core/operations/management/query_index_create.hxx +2 -0
  40. package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.cxx +11 -16
  41. package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.hxx +2 -0
  42. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.cxx +8 -12
  43. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.hxx +4 -3
  44. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.cxx +21 -12
  45. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.hxx +3 -2
  46. package/deps/couchbase-cxx-client/core/origin.hxx +1 -1
  47. package/deps/couchbase-cxx-client/core/platform/uuid.cc +1 -2
  48. package/deps/couchbase-cxx-client/core/protocol/cmd_hello.hxx +5 -1
  49. package/deps/couchbase-cxx-client/core/query_context.hxx +79 -0
  50. package/deps/couchbase-cxx-client/core/tracing/CMakeLists.txt +3 -1
  51. package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.cxx +19 -4
  52. package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.hxx +2 -2
  53. package/deps/couchbase-cxx-client/core/transactions/async_attempt_context.hxx +10 -4
  54. package/deps/couchbase-cxx-client/core/transactions/atr_cleanup_entry.cxx +52 -63
  55. package/deps/couchbase-cxx-client/core/transactions/attempt_context.hxx +8 -3
  56. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +163 -126
  57. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.hxx +24 -37
  58. package/deps/couchbase-cxx-client/core/transactions/forward_compat.hxx +4 -4
  59. package/deps/couchbase-cxx-client/core/transactions/internal/atr_cleanup_entry.hxx +51 -13
  60. package/deps/couchbase-cxx-client/core/transactions/internal/client_record.hxx +26 -1
  61. package/deps/couchbase-cxx-client/core/transactions/internal/doc_record.hxx +21 -0
  62. package/deps/couchbase-cxx-client/core/transactions/internal/logging.hxx +40 -18
  63. package/deps/couchbase-cxx-client/core/transactions/internal/transaction_context.hxx +5 -0
  64. package/deps/couchbase-cxx-client/core/transactions/result.hxx +26 -0
  65. package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +48 -47
  66. package/deps/couchbase-cxx-client/core/transactions/staged_mutation.hxx +6 -6
  67. package/deps/couchbase-cxx-client/core/transactions/transaction_context.cxx +33 -19
  68. package/deps/couchbase-cxx-client/core/transactions/transaction_get_result.hxx +18 -2
  69. package/deps/couchbase-cxx-client/core/transactions/transaction_links.hxx +25 -2
  70. package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +4 -4
  71. package/deps/couchbase-cxx-client/core/transactions/transactions_cleanup.cxx +49 -56
  72. package/deps/couchbase-cxx-client/core/transactions/waitable_op_list.hxx +7 -7
  73. package/deps/couchbase-cxx-client/core/transactions.hxx +0 -12
  74. package/deps/couchbase-cxx-client/core/utils/binary.hxx +1 -1
  75. package/deps/couchbase-cxx-client/core/utils/keyspace.hxx +55 -0
  76. package/deps/couchbase-cxx-client/couchbase/build_query_index_options.hxx +12 -45
  77. package/deps/couchbase-cxx-client/couchbase/cluster.hxx +1 -1
  78. package/deps/couchbase-cxx-client/couchbase/cluster_options.hxx +6 -7
  79. package/deps/couchbase-cxx-client/couchbase/collection.hxx +8 -0
  80. package/deps/couchbase-cxx-client/couchbase/collection_query_index_manager.hxx +218 -0
  81. package/deps/couchbase-cxx-client/couchbase/configuration_profiles_registry.hxx +3 -0
  82. package/deps/couchbase-cxx-client/couchbase/create_primary_query_index_options.hxx +166 -0
  83. package/deps/couchbase-cxx-client/couchbase/create_query_index_options.hxx +172 -0
  84. package/deps/couchbase-cxx-client/couchbase/drop_primary_query_index_options.hxx +129 -0
  85. package/deps/couchbase-cxx-client/couchbase/drop_query_index_options.hxx +116 -0
  86. package/deps/couchbase-cxx-client/couchbase/fmt/cas.hxx +1 -1
  87. package/deps/couchbase-cxx-client/couchbase/fmt/query_scan_consistency.hxx +46 -0
  88. package/deps/couchbase-cxx-client/couchbase/fmt/query_status.hxx +70 -0
  89. package/deps/couchbase-cxx-client/couchbase/fmt/tls_verify_mode.hxx +46 -0
  90. package/deps/couchbase-cxx-client/couchbase/get_all_query_indexes_options.hxx +100 -0
  91. package/deps/couchbase-cxx-client/{core → couchbase}/management/query_index.hxx +2 -2
  92. package/deps/couchbase-cxx-client/couchbase/metrics/meter.hxx +16 -0
  93. package/deps/couchbase-cxx-client/couchbase/query_index_manager.hxx +178 -6
  94. package/deps/couchbase-cxx-client/couchbase/query_options.hxx +1 -18
  95. package/deps/couchbase-cxx-client/couchbase/scope.hxx +5 -2
  96. package/deps/couchbase-cxx-client/couchbase/tracing/request_tracer.hxx +16 -0
  97. package/deps/couchbase-cxx-client/couchbase/transactions/async_attempt_context.hxx +11 -4
  98. package/deps/couchbase-cxx-client/couchbase/transactions/attempt_context.hxx +5 -3
  99. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_keyspace.hxx +16 -0
  100. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_query_options.hxx +0 -6
  101. package/deps/couchbase-cxx-client/couchbase/watch_query_indexes_options.hxx +115 -0
  102. package/deps/couchbase-cxx-client/examples/minimal.cxx +3 -1
  103. package/deps/couchbase-cxx-client/test/test_integration_crud.cxx +72 -0
  104. package/deps/couchbase-cxx-client/test/test_integration_management.cxx +727 -310
  105. package/deps/couchbase-cxx-client/test/test_integration_query.cxx +4 -8
  106. package/deps/couchbase-cxx-client/test/test_integration_transcoders.cxx +14 -0
  107. package/deps/couchbase-cxx-client/test/test_transaction_transaction_public_blocking_api.cxx +34 -19
  108. package/deps/couchbase-cxx-client/test/test_unit_transaction_logging.cxx +66 -22
  109. package/deps/couchbase-cxx-client/test/test_unit_utils.cxx +51 -0
  110. package/deps/couchbase-cxx-client/test/tools/tool_kv_loader.cxx +2 -2
  111. package/deps/couchbase-cxx-client/test/utils/integration_test_guard.cxx +2 -0
  112. package/deps/couchbase-cxx-client/test/utils/wait_until.cxx +4 -4
  113. package/deps/couchbase-cxx-client/third_party/docopt/.travis.yml +103 -0
  114. package/deps/couchbase-cxx-client/third_party/docopt/CMakeLists.txt +129 -0
  115. package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-Boost-1.0 +23 -0
  116. package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-MIT +23 -0
  117. package/deps/couchbase-cxx-client/third_party/docopt/README.rst +479 -0
  118. package/deps/couchbase-cxx-client/third_party/docopt/docopt-config.cmake +1 -0
  119. package/deps/couchbase-cxx-client/third_party/docopt/docopt.cpp +687 -0
  120. package/deps/couchbase-cxx-client/third_party/docopt/docopt.h +98 -0
  121. package/deps/couchbase-cxx-client/third_party/docopt/docopt.pc.in +9 -0
  122. package/deps/couchbase-cxx-client/third_party/docopt/docopt_private.h +676 -0
  123. package/deps/couchbase-cxx-client/third_party/docopt/docopt_util.h +122 -0
  124. package/deps/couchbase-cxx-client/third_party/docopt/docopt_value.h +341 -0
  125. package/deps/couchbase-cxx-client/third_party/docopt/examples/naval_fate.cpp +36 -0
  126. package/deps/couchbase-cxx-client/third_party/docopt/main.cpp +16 -0
  127. package/deps/couchbase-cxx-client/third_party/docopt/run_testcase.cpp +40 -0
  128. package/deps/couchbase-cxx-client/third_party/docopt/run_tests.py +72 -0
  129. package/deps/couchbase-cxx-client/third_party/docopt/testcases.docopt +957 -0
  130. package/deps/couchbase-cxx-client/tools/CMakeLists.txt +14 -0
  131. package/deps/couchbase-cxx-client/tools/cbc.cxx +65 -0
  132. package/deps/couchbase-cxx-client/tools/command.hxx +31 -0
  133. package/deps/couchbase-cxx-client/tools/command_registry.cxx +43 -0
  134. package/deps/couchbase-cxx-client/tools/command_registry.hxx +39 -0
  135. package/deps/couchbase-cxx-client/tools/get.cxx +267 -0
  136. package/deps/couchbase-cxx-client/tools/get.hxx +26 -0
  137. package/deps/couchbase-cxx-client/tools/query.cxx +441 -0
  138. package/deps/couchbase-cxx-client/tools/query.hxx +26 -0
  139. package/deps/couchbase-cxx-client/tools/utils.cxx +418 -0
  140. package/deps/couchbase-cxx-client/tools/utils.hxx +150 -0
  141. package/deps/couchbase-cxx-client/tools/version.cxx +82 -0
  142. package/deps/couchbase-cxx-client/tools/version.hxx +26 -0
  143. package/dist/authenticators.d.ts +2 -2
  144. package/dist/authenticators.js +1 -2
  145. package/dist/binding.d.ts +32 -16
  146. package/dist/cluster.js +14 -7
  147. package/dist/collection.d.ts +6 -0
  148. package/dist/collection.js +8 -0
  149. package/dist/queryexecutor.js +1 -1
  150. package/dist/queryindexmanager.d.ts +100 -4
  151. package/dist/queryindexmanager.js +344 -118
  152. package/dist/transactions.js +0 -2
  153. package/package.json +1 -1
  154. package/src/connection.cpp +2 -0
  155. package/src/connection.hpp +1 -0
  156. package/src/connection_autogen.cpp +16 -0
  157. package/src/jstocbpp_autogen.hpp +93 -23
  158. package/src/jstocbpp_basic.hpp +24 -0
  159. package/src/jstocbpp_transactions.hpp +0 -8
  160. package/tools/gen-bindings-js.js +1 -0
  161. package/tools/gen-bindings-json.py +4 -2
  162. package/deps/couchbase-cxx-client/core/transactions/logging.cxx +0 -107
@@ -64,9 +64,8 @@ transactions_cleanup::transactions_cleanup(std::shared_ptr<core::cluster> cluste
64
64
  static uint64_t
65
65
  byteswap64(uint64_t val)
66
66
  {
67
- std::size_t ii;
68
67
  uint64_t ret = 0;
69
- for (ii = 0; ii < sizeof(uint64_t); ii++) {
68
+ for (std::size_t ii = 0; ii < sizeof(uint64_t); ii++) {
70
69
  ret <<= 8ull;
71
70
  ret |= val & 0xffull;
72
71
  val >>= 8ull;
@@ -130,12 +129,11 @@ transactions_cleanup::clean_collection(const couchbase::transactions::transactio
130
129
  {
131
130
  std::lock_guard<std::mutex> lock(mutex_);
132
131
  if (collections_.end() == std::find(collections_.begin(), collections_.end(), keyspace)) {
133
- lost_attempts_cleanup_log->info(
134
- "{} cleanup for {} ending, no longer in collection cleanup list", static_cast<void*>(this), keyspace);
132
+ CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup for {} ending, no longer in collection cleanup list", keyspace);
135
133
  return;
136
134
  }
137
135
  }
138
- lost_attempts_cleanup_log->info("{} cleanup for {} starting", static_cast<void*>(this), keyspace);
136
+ CB_LOST_ATTEMPT_CLEANUP_LOG_INFO("cleanup for {} starting", keyspace);
139
137
  // we are running, and collection is in the list, so lets clean it.
140
138
  try {
141
139
  auto details = get_active_clients(keyspace, client_uuid_);
@@ -145,11 +143,10 @@ transactions_cleanup::clean_collection(const couchbase::transactions::transactio
145
143
  std::chrono::microseconds cleanup_window =
146
144
  std::chrono::duration_cast<std::chrono::microseconds>(config_.cleanup_config.cleanup_window);
147
145
  auto start = std::chrono::steady_clock::now();
148
- lost_attempts_cleanup_log->info("{} {} active clients (including this one), {} ATRs to check in {}ms",
149
- static_cast<void*>(this),
150
- details.num_active_clients,
151
- all_atrs.size(),
152
- config_.cleanup_config.cleanup_window.count());
146
+ CB_LOST_ATTEMPT_CLEANUP_LOG_INFO("{} active clients (including this one), {} ATRs to check in {}ms",
147
+ details.num_active_clients,
148
+ all_atrs.size(),
149
+ config_.cleanup_config.cleanup_window.count());
153
150
 
154
151
  for (auto it = all_atrs.begin() + details.index_of_this_client; it < all_atrs.end(); it += details.num_active_clients) {
155
152
  auto atrs_left_for_this_client =
@@ -162,15 +159,14 @@ transactions_cleanup::clean_collection(const couchbase::transactions::transactio
162
159
  // clean the ATR entry
163
160
  std::string atr_id = *it;
164
161
  if (!running_.load()) {
165
- lost_attempts_cleanup_log->debug("{} cleanup of {} complete", static_cast<void*>(this), keyspace);
162
+ CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup of {} complete", keyspace);
166
163
  return;
167
164
  }
168
165
 
169
166
  try {
170
167
  handle_atr_cleanup({ keyspace.bucket, keyspace.scope, keyspace.collection, atr_id });
171
168
  } catch (const std::exception& e) {
172
- lost_attempts_cleanup_log->error(
173
- "{} cleanup of atr {} failed with {}, moving on", static_cast<void*>(this), atr_id, e.what());
169
+ CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR("cleanup of atr {} failed with {}, moving on", atr_id, e.what());
174
170
  }
175
171
 
176
172
  auto atr_end = std::chrono::steady_clock::now();
@@ -178,7 +174,7 @@ transactions_cleanup::clean_collection(const couchbase::transactions::transactio
178
174
  std::chrono::microseconds atr_left = budget_for_this_atr - atr_used;
179
175
 
180
176
  // Too verbose to log, but leaving here commented as it may be useful later for internal debugging
181
- /*lost_attempts_cleanup_log->info("{} {} atrs_left_for_this_client={} elapsed_in_cleanup_window={}us "
177
+ /*CB_LOST_ATTEMPT_CLEANUP_LOG_INFO("{} {} atrs_left_for_this_client={} elapsed_in_cleanup_window={}us "
182
178
  "remaining_in_cleanup_window={}us budget_for_this_atr={}us atr_used={}us atr_left={}us",
183
179
  bucket_name,
184
180
  atr_id,
@@ -194,7 +190,7 @@ transactions_cleanup::clean_collection(const couchbase::transactions::transactio
194
190
  }
195
191
  }
196
192
  } catch (const std::exception& ex) {
197
- lost_attempts_cleanup_log->error("{} cleanup failed with {}, trying again in 3 sec...", static_cast<void*>(this), ex.what());
193
+ CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR("cleanup failed with {}, trying again in 3 sec...", ex.what());
198
194
  // we must have gotten an exception trying to get the client records. Let's wait 3 sec and try again
199
195
  std::this_thread::sleep_for(std::chrono::seconds(3));
200
196
  }
@@ -219,13 +215,12 @@ transactions_cleanup::handle_atr_cleanup(const core::document_id& atr_id, std::v
219
215
  if (results) {
220
216
  results->emplace_back(cleanup_entry);
221
217
  }
222
- cleanup_entry.clean(lost_attempts_cleanup_log, results ? &results->back() : nullptr);
218
+ cleanup_entry.clean(results ? &results->back() : nullptr);
223
219
  if (results) {
224
220
  results->back().success(true);
225
221
  }
226
222
  } catch (const std::exception& e) {
227
- lost_attempts_cleanup_log->error(
228
- "{} cleanup of {} failed: {}, moving on", static_cast<void*>(this), cleanup_entry, e.what());
223
+ CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR("cleanup of {} failed: {}, moving on", cleanup_entry, e.what());
229
224
  if (results) {
230
225
  results->back().success(false);
231
226
  }
@@ -263,11 +258,11 @@ transactions_cleanup::create_client_record(const couchbase::transactions::transa
263
258
  wrap_operation_future(f);
264
259
 
265
260
  } catch (const client_error& e) {
266
- lost_attempts_cleanup_log->trace("{} create_client_record got error {}", static_cast<void*>(this), e.what());
261
+ CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("create_client_record got error {}", e.what());
267
262
  auto ec = e.ec();
268
263
  switch (ec) {
269
264
  case FAIL_DOC_ALREADY_EXISTS:
270
- lost_attempts_cleanup_log->trace("{} client record already exists, moving on", static_cast<void*>(this));
265
+ CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("client record already exists, moving on");
271
266
  return;
272
267
  default:
273
268
  throw;
@@ -313,7 +308,7 @@ transactions_cleanup::get_active_clients(const couchbase::transactions::transact
313
308
  details.override_expires = 0;
314
309
  if (res.values[0].status == subdoc_result::status_type::success) {
315
310
  auto records = res.values[0].content_as();
316
- lost_attempts_cleanup_log->trace("client records: {}", core::utils::json::generate(records));
311
+ CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("client records: {}", core::utils::json::generate(records));
317
312
  for (const auto& [key, value] : records.get_object()) {
318
313
  if (key == FIELD_OVERRIDE) {
319
314
  for (const auto& [override, param] : value.get_object()) {
@@ -352,9 +347,9 @@ transactions_cleanup::get_active_clients(const couchbase::transactions::transact
352
347
  details.client_uuid = uuid;
353
348
  details.cas_now_nanos = now_ms * 1000000;
354
349
  details.override_active = (details.override_enabled && details.override_expires > details.cas_now_nanos);
355
- lost_attempts_cleanup_log->trace("{} client details {}", static_cast<void*>(this), details);
350
+ CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("client details {}", details);
356
351
  if (details.override_active) {
357
- lost_attempts_cleanup_log->trace("{} override enabled, will not update record", static_cast<void*>(this));
352
+ CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("override enabled, will not update record");
358
353
  return details;
359
354
  }
360
355
 
@@ -373,8 +368,8 @@ transactions_cleanup::get_active_clients(const couchbase::transactions::transact
373
368
  .create_path(),
374
369
  };
375
370
  for (std::size_t idx = 0; idx < std::min(details.expired_client_ids.size(), static_cast<std::size_t>(12)); idx++) {
376
- lost_attempts_cleanup_log->trace("adding {} to list of clients to be removed when updating this client",
377
- details.expired_client_ids[idx]);
371
+ CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("adding {} to list of clients to be removed when updating this client",
372
+ details.expired_client_ids[idx]);
378
373
  mut_specs.push_back(couchbase::mutate_in_specs::remove(FIELD_CLIENTS + "." + details.expired_client_ids[idx]).xattr());
379
374
  }
380
375
  mutate_req.specs = mut_specs.specs();
@@ -385,7 +380,7 @@ transactions_cleanup::get_active_clients(const couchbase::transactions::transact
385
380
  wrap_durable_request(mutate_req, config_);
386
381
  auto mutate_barrier = std::make_shared<std::promise<result>>();
387
382
  auto mutate_f = mutate_barrier->get_future();
388
- lost_attempts_cleanup_log->trace("updating record");
383
+ CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("updating record");
389
384
  cluster_->execute(mutate_req, [mutate_barrier](core::operations::mutate_in_response resp) {
390
385
  mutate_barrier->set_value(result::create_from_subdoc_response(resp));
391
386
  });
@@ -393,17 +388,17 @@ transactions_cleanup::get_active_clients(const couchbase::transactions::transact
393
388
 
394
389
  // just update the cas, and return the details
395
390
  details.cas_now_nanos = res.cas;
396
- lost_attempts_cleanup_log->debug("{} get_active_clients found {}", static_cast<void*>(this), details);
391
+ CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("get_active_clients found {}", details);
397
392
  return details;
398
393
  } catch (const client_error& e) {
399
394
  auto ec = e.ec();
400
395
  switch (ec) {
401
396
  case FAIL_DOC_NOT_FOUND:
402
- lost_attempts_cleanup_log->debug("{} client record not found, creating new one", static_cast<void*>(this));
397
+ CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("client record not found, creating new one");
403
398
  create_client_record(keyspace);
404
399
  throw retry_operation("Client record didn't exist. Creating and retrying");
405
400
  default:
406
- throw; // retry_operation(fmt::format("got error '' while processing client record, retrying...", e.what()));
401
+ throw;
407
402
  }
408
403
  }
409
404
  });
@@ -438,17 +433,16 @@ transactions_cleanup::remove_client_record_from_all_buckets(const std::string& u
438
433
  barrier->set_value(result::create_from_subdoc_response(resp));
439
434
  });
440
435
  wrap_operation_future(f);
441
- lost_attempts_cleanup_log->debug("{} removed {} from {}", static_cast<void*>(this), uuid, keyspace);
436
+ CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("removed {} from {}", uuid, keyspace);
442
437
  } catch (const client_error& e) {
443
- lost_attempts_cleanup_log->debug("{} error removing client records {}", static_cast<void*>(this), e.what());
438
+ CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("error removing client records {}", e.what());
444
439
  auto ec = e.ec();
445
440
  switch (ec) {
446
441
  case FAIL_DOC_NOT_FOUND:
447
- lost_attempts_cleanup_log->debug("{} no client record in {}, ignoring", static_cast<void*>(this), keyspace);
442
+ CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("no client record in {}, ignoring", keyspace);
448
443
  return;
449
444
  case FAIL_PATH_NOT_FOUND:
450
- lost_attempts_cleanup_log->debug(
451
- "{} client {} not in client record for {}, ignoring", static_cast<void*>(this), uuid, keyspace);
445
+ CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("client {} not in client record for {}, ignoring", uuid, keyspace);
452
446
  return;
453
447
  default:
454
448
  throw retry_operation("retry remove until timeout");
@@ -456,8 +450,7 @@ transactions_cleanup::remove_client_record_from_all_buckets(const std::string& u
456
450
  }
457
451
  });
458
452
  } catch (const std::exception& e) {
459
- lost_attempts_cleanup_log->error(
460
- "{} Error removing client record {} from {}: {}", static_cast<void*>(this), uuid, keyspace, e.what());
453
+ CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR("Error removing client record {} from {}: {}", uuid, keyspace, e.what());
461
454
  }
462
455
  }
463
456
  }
@@ -465,7 +458,7 @@ transactions_cleanup::remove_client_record_from_all_buckets(const std::string& u
465
458
  const atr_cleanup_stats
466
459
  transactions_cleanup::force_cleanup_atr(const core::document_id& atr_id, std::vector<transactions_cleanup_attempt>& results)
467
460
  {
468
- lost_attempts_cleanup_log->trace("{} starting force_cleanup_atr: atr_id {}", static_cast<void*>(this), atr_id);
461
+ CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("starting force_cleanup_atr: atr_id {}", atr_id);
469
462
  return handle_atr_cleanup(atr_id, &results);
470
463
  }
471
464
 
@@ -473,11 +466,11 @@ void
473
466
  transactions_cleanup::force_cleanup_entry(atr_cleanup_entry& entry, transactions_cleanup_attempt& attempt)
474
467
  {
475
468
  try {
476
- entry.clean(attempt_cleanup_log, &attempt);
469
+ entry.clean(&attempt);
477
470
  attempt.success(true);
478
471
 
479
472
  } catch (const std::runtime_error& e) {
480
- attempt_cleanup_log->error("error attempting to clean {}: {}", entry, e.what());
473
+ CB_ATTEMPT_CLEANUP_LOG_ERROR("error attempting to clean {}: {}", entry, e.what());
481
474
  attempt.success(false);
482
475
  }
483
476
  }
@@ -485,16 +478,16 @@ transactions_cleanup::force_cleanup_entry(atr_cleanup_entry& entry, transactions
485
478
  void
486
479
  transactions_cleanup::force_cleanup_attempts(std::vector<transactions_cleanup_attempt>& results)
487
480
  {
488
- attempt_cleanup_log->trace("starting force_cleanup_attempts");
481
+ CB_ATTEMPT_CLEANUP_LOG_TRACE("starting force_cleanup_attempts");
489
482
  while (atr_queue_.size() > 0) {
490
483
  auto entry = atr_queue_.pop(false);
491
484
  if (!entry) {
492
- attempt_cleanup_log->error("pop failed to return entry, but queue size {}", atr_queue_.size());
485
+ CB_ATTEMPT_CLEANUP_LOG_ERROR("pop failed to return entry, but queue size {}", atr_queue_.size());
493
486
  return;
494
487
  }
495
488
  results.emplace_back(*entry);
496
489
  try {
497
- entry->clean(attempt_cleanup_log, &results.back());
490
+ entry->clean(&results.back());
498
491
  results.back().success(true);
499
492
  } catch (std::runtime_error&) {
500
493
  results.back().success(false);
@@ -506,27 +499,27 @@ void
506
499
  transactions_cleanup::attempts_loop()
507
500
  {
508
501
  try {
509
- attempt_cleanup_log->debug("cleanup attempts loop starting...");
502
+ CB_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup attempts loop starting...");
510
503
  while (interruptable_wait(cleanup_loop_delay_)) {
511
504
  while (auto entry = atr_queue_.pop()) {
512
505
  if (!running_.load()) {
513
- attempt_cleanup_log->debug("loop stopping - {} entries on queue", atr_queue_.size());
506
+ CB_ATTEMPT_CLEANUP_LOG_DEBUG("loop stopping - {} entries on queue", atr_queue_.size());
514
507
  return;
515
508
  }
516
509
  if (entry) {
517
- attempt_cleanup_log->trace("beginning cleanup on {}", *entry);
510
+ CB_ATTEMPT_CLEANUP_LOG_TRACE("beginning cleanup on {}", *entry);
518
511
  try {
519
- entry->clean(attempt_cleanup_log);
512
+ entry->clean();
520
513
  } catch (...) {
521
514
  // catch everything as we don't want to raise out of this thread
522
- attempt_cleanup_log->info("got error cleaning {}, leaving for lost txn cleanup", entry.value());
515
+ CB_ATTEMPT_CLEANUP_LOG_DEBUG("got error cleaning {}, leaving for lost txn cleanup", entry.value());
523
516
  }
524
517
  }
525
518
  }
526
519
  }
527
- attempt_cleanup_log->info("stopping - {} entries on queue", atr_queue_.size());
520
+ CB_ATTEMPT_CLEANUP_LOG_DEBUG("stopping - {} entries on queue", atr_queue_.size());
528
521
  } catch (const std::runtime_error& e) {
529
- attempt_cleanup_log->error("got error \"{}\" in attempts_loop", e.what());
522
+ CB_ATTEMPT_CLEANUP_LOG_ERROR("got error \"{}\" in attempts_loop", e.what());
530
523
  }
531
524
  }
532
525
 
@@ -538,14 +531,14 @@ transactions_cleanup::add_attempt(attempt_context& ctx)
538
531
  case attempt_state::NOT_STARTED:
539
532
  case attempt_state::COMPLETED:
540
533
  case attempt_state::ROLLED_BACK:
541
- attempt_cleanup_log->trace("attempt in state {}, not adding to cleanup", attempt_state_name(ctx_impl.state()));
534
+ CB_ATTEMPT_CLEANUP_LOG_TRACE("attempt in state {}, not adding to cleanup", attempt_state_name(ctx_impl.state()));
542
535
  return;
543
536
  default:
544
537
  if (config_.cleanup_config.cleanup_client_attempts) {
545
- attempt_cleanup_log->debug("adding attempt {} to cleanup queue", ctx_impl.id());
538
+ CB_ATTEMPT_CLEANUP_LOG_DEBUG("adding attempt {} to cleanup queue", ctx_impl.id());
546
539
  atr_queue_.push(ctx);
547
540
  } else {
548
- attempt_cleanup_log->trace("not cleaning client attempts, ignoring {}", ctx_impl.id());
541
+ CB_ATTEMPT_CLEANUP_LOG_TRACE("not cleaning client attempts, ignoring {}", ctx_impl.id());
549
542
  }
550
543
  }
551
544
  }
@@ -564,7 +557,7 @@ transactions_cleanup::add_collection(couchbase::transactions::transaction_keyspa
564
557
  lost_attempt_cleanup_workers_.emplace_back([this, keyspace = collections_.back()]() { this->clean_collection(keyspace); });
565
558
  }
566
559
  lock.unlock();
567
- lost_attempts_cleanup_log->info("added {} to lost transaction cleanup", keyspace);
560
+ CB_ATTEMPT_CLEANUP_LOG_DEBUG("added {} to lost transaction cleanup", keyspace);
568
561
  }
569
562
  }
570
563
 
@@ -578,15 +571,15 @@ transactions_cleanup::close()
578
571
  }
579
572
  if (cleanup_thr_.joinable()) {
580
573
  cleanup_thr_.join();
581
- attempt_cleanup_log->info("cleanup attempt thread closed");
574
+ CB_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup attempt thread closed");
582
575
  }
583
576
  for (auto& t : lost_attempt_cleanup_workers_) {
584
- lost_attempts_cleanup_log->info("shutting down all lost attempt threads...");
577
+ CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("shutting down all lost attempt threads...");
585
578
  if (t.joinable()) {
586
579
  t.join();
587
580
  }
588
581
  }
589
- lost_attempts_cleanup_log->info("all lost attempt cleanup threads closed");
582
+ CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("all lost attempt cleanup threads closed");
590
583
  if (true) {
591
584
  remove_client_record_from_all_buckets(client_uuid_);
592
585
  }
@@ -98,11 +98,11 @@ class waitable_op_list
98
98
  in_flight_--;
99
99
  if (mode_.mode == attempt_mode::modes::KV) {
100
100
  // wait until all in_flight ops are done
101
- txn_log->trace("set_query_mode: waiting for in_flight ops to go to 0...");
101
+ CB_TXN_LOG_TRACE("set_query_mode: waiting for in_flight ops to go to 0...");
102
102
  cv_in_flight_.wait(lock, [this]() { return (0 == in_flight_); });
103
103
  // ok, now no outstanding ops(apart from the query that called this), and I have the lock, so...
104
104
  if (mode_.mode == attempt_mode::modes::KV) {
105
- txn_log->trace("set_query_mode: in_flight ops = 0, we were kv, setting mode to query");
105
+ CB_TXN_LOG_TRACE("set_query_mode: in_flight ops = 0, we were kv, setting mode to query");
106
106
  // still kv, so now (while blocking) set the mode
107
107
  mode_.mode = attempt_mode::modes::QUERY;
108
108
  // ok to unlock now, as any racing set_query_mode will wait for
@@ -117,10 +117,10 @@ class waitable_op_list
117
117
  }
118
118
  // you make it here, and someone else is currently setting the node (a byproduct of
119
119
  // calling the callback). So wait for that.
120
- txn_log->trace("set_query_mode: mode already query, waiting for node to be set...");
120
+ CB_TXN_LOG_TRACE("set_query_mode: mode already query, waiting for node to be set...");
121
121
  cv_query_.wait(lock, [this]() { return !mode_.query_node.empty(); });
122
122
  in_flight_++;
123
- txn_log->trace("set_query_mode: node set, continuing...");
123
+ CB_TXN_LOG_TRACE("set_query_mode: node set, continuing...");
124
124
  lock.unlock();
125
125
  cb();
126
126
  }
@@ -145,7 +145,7 @@ class waitable_op_list
145
145
  {
146
146
  std::lock_guard<std::mutex> lock(mutex_);
147
147
  in_flight_--;
148
- txn_log->trace("in_flight decremented to {}", in_flight_);
148
+ CB_TXN_LOG_TRACE("in_flight decremented to {}", in_flight_);
149
149
  assert(in_flight_ >= 0);
150
150
  if (0 == in_flight_) {
151
151
  cv_in_flight_.notify_all();
@@ -161,7 +161,7 @@ class waitable_op_list
161
161
  if (val > 0) {
162
162
  in_flight_ += val;
163
163
  }
164
- txn_log->trace("op count changed by {} to {}, {} in_flight", val, count_, in_flight_);
164
+ CB_TXN_LOG_TRACE("op count changed by {} to {}, {} in_flight", val, count_, in_flight_);
165
165
  assert(count_ >= 0);
166
166
  assert(in_flight_ >= 0);
167
167
  if (0 == count_) {
@@ -171,7 +171,7 @@ class waitable_op_list
171
171
  cv_in_flight_.notify_all();
172
172
  }
173
173
  } else {
174
- txn_log->error("operation attempted after commit/rollback");
174
+ CB_TXN_LOG_ERROR("operation attempted after commit/rollback");
175
175
  throw async_operation_conflict("Operation attempted after commit or rollback");
176
176
  }
177
177
  }
@@ -61,18 +61,6 @@ using async_logic = std::function<void(async_attempt_context&)>;
61
61
  using txn_complete_callback =
62
62
  std::function<void(std::optional<transaction_exception>, std::optional<::couchbase::transactions::transaction_result>)>;
63
63
 
64
- /**
65
- * @brief set log level for transactions
66
- */
67
- void
68
- set_transactions_log_level(core::logger::level level);
69
-
70
- /**
71
- * @brief create the loggers, using a custom spdlog::sink, if desired.
72
- */
73
- void
74
- create_loggers(core::logger::level level = core::logger::level::off, spdlog::sink_ptr = nullptr);
75
-
76
64
  /**
77
65
  * @mainpage
78
66
  * A transaction consists of a lambda containing all the operations you wish to perform within a transaction.
@@ -34,7 +34,7 @@ to_binary(const T* data, const std::size_t size) noexcept
34
34
  static_assert(sizeof(T) == 1);
35
35
  binary copy;
36
36
  copy.reserve(size);
37
- std::transform(data, data + size, std::back_insert_iterator(copy), [](auto e) { return static_cast<std::byte>(e); });
37
+ copy.insert(copy.end(), reinterpret_cast<const std::byte*>(data), reinterpret_cast<const std::byte*>(data + size));
38
38
  return copy;
39
39
  }
40
40
 
@@ -0,0 +1,55 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020-2021 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <fmt/format.h>
21
+ #include <string>
22
+
23
+ namespace couchbase::core::utils
24
+ {
25
+ template<typename Request>
26
+ static bool
27
+ check_query_management_request(const Request& req)
28
+ {
29
+ // if there is a query_context, then bucket, scope should not be specified, but collection should be.
30
+ // collection should be.
31
+ if (req.query_ctx.has_value()) {
32
+ return !req.collection_name.empty() && req.bucket_name.empty() && req.scope_name.empty();
33
+ }
34
+ // otherwise, both scope and collection must be specified, if one is
35
+ // and bucket _must_ be there as well.
36
+ return !req.bucket_name.empty() &&
37
+ ((req.scope_name.empty() && req.collection_name.empty()) || (!req.scope_name.empty() && !req.collection_name.empty()));
38
+ }
39
+
40
+ template<typename Request>
41
+ static std::string
42
+ build_keyspace(const Request& req)
43
+ {
44
+ // keyspace is just the collection if we have a query_context.
45
+ if (req.query_ctx.has_value()) {
46
+ return fmt::format("{}.`{}`", req.query_ctx.value(), req.collection_name);
47
+ }
48
+ // otherwise, build from the bucket, scope and collection names in request...
49
+ if (req.scope_name.empty() && req.collection_name.empty()) {
50
+ return fmt::format("{}:`{}`", req.namespace_id, req.bucket_name);
51
+ }
52
+ return fmt::format("{}:`{}`.`{}`.`{}`", req.namespace_id, req.bucket_name, req.scope_name, req.collection_name);
53
+ }
54
+
55
+ } // namespace couchbase::core::utils
@@ -18,6 +18,7 @@
18
18
  #pragma once
19
19
 
20
20
  #include <couchbase/common_options.hxx>
21
+ #include <couchbase/error_codes.hxx>
21
22
  #include <couchbase/manager_error_context.hxx>
22
23
 
23
24
  #include <functional>
@@ -36,40 +37,6 @@ namespace couchbase
36
37
  class build_query_index_options : public common_options<build_query_index_options>
37
38
  {
38
39
  public:
39
- /**
40
- * Sets the scope name for this query management operation.
41
- *
42
- * Please note that if the scope name is set, the {@link #collection_name} must also be set.
43
- *
44
- * @since 1.0.0
45
- * @committed
46
- */
47
- auto scope_name(std::string scope_name) -> build_query_index_options&
48
- {
49
- scope_name_.emplace(std::move(scope_name));
50
- return self();
51
- }
52
-
53
- /**
54
- * Sets the collection name for this query management operation.
55
- *
56
- * Please note that if the collection name is set, the {@link #scope_name} must also be set.
57
- *
58
- * @since 1.0.0
59
- * @committed
60
- */
61
- auto collection_name(std::string collection_name) -> build_query_index_options&
62
- {
63
- collection_name_.emplace(std::move(collection_name));
64
- return self();
65
- }
66
-
67
- /**
68
- * Immutable value object representing consistent options.
69
- *
70
- * @since 1.0.0
71
- * @internal
72
- */
73
40
  struct built : public common_options<build_query_index_options>::built {
74
41
  const std::optional<std::string> scope_name{};
75
42
  const std::optional<std::string> collection_name{};
@@ -87,18 +54,9 @@ class build_query_index_options : public common_options<build_query_index_option
87
54
  */
88
55
  [[nodiscard]] auto build() const -> built
89
56
  {
90
- if (scope_name_.has_value() && !collection_name_.has_value()) {
91
- throw std::system_error(errc::common::invalid_argument, "if a scope_name is provided, a collection_name must also be provided");
92
- }
93
- if (!scope_name_.has_value() && collection_name_.has_value()) {
94
- throw std::system_error(errc::common::invalid_argument, "if a collection_name is provided, a scope_name must also be provided");
95
- }
96
- return { build_common_options(), scope_name_, collection_name_ };
97
- }
98
57
 
99
- private:
100
- std::optional<std::string> scope_name_{};
101
- std::optional<std::string> collection_name_{};
58
+ return { build_common_options() };
59
+ }
102
60
  };
103
61
 
104
62
  /**
@@ -113,6 +71,7 @@ using build_deferred_query_indexes_handler = std::function<void(couchbase::manag
113
71
  namespace core
114
72
  {
115
73
  class cluster;
74
+ class query_context;
116
75
  namespace impl
117
76
  {
118
77
 
@@ -121,6 +80,14 @@ namespace impl
121
80
  * @internal
122
81
  */
123
82
  void
83
+ initiate_build_deferred_indexes(std::shared_ptr<couchbase::core::cluster> resp1,
84
+ std::string bucket_name,
85
+ build_query_index_options::built options,
86
+ query_context query_ctx,
87
+ std::string collection_name,
88
+ build_deferred_query_indexes_handler&& handler);
89
+
90
+ void
124
91
  initiate_build_deferred_indexes(std::shared_ptr<couchbase::core::cluster> resp1,
125
92
  std::string bucket_name,
126
93
  build_query_index_options::built options,
@@ -141,7 +141,7 @@ class cluster
141
141
  template<typename Handler>
142
142
  void query(std::string statement, const query_options& options, Handler&& handler) const
143
143
  {
144
- return core::impl::initiate_query_operation(core_, std::move(statement), {}, {}, options.build(), std::forward<Handler>(handler));
144
+ return core::impl::initiate_query_operation(core_, std::move(statement), {}, options.build(), std::forward<Handler>(handler));
145
145
  }
146
146
 
147
147
  /**
@@ -72,8 +72,10 @@ class cluster_options
72
72
  explicit cluster_options(password_authenticator authenticator)
73
73
  : username_{ std::move(authenticator.username_) }
74
74
  , password_{ std::move(authenticator.password_) }
75
- , ldap_compatible_{ authenticator.ldap_compatible_ }
76
75
  {
76
+ if (authenticator.ldap_compatible_) {
77
+ sasl_mechanisms_ = { { "PLAIN" } };
78
+ }
77
79
  }
78
80
 
79
81
  /**
@@ -246,7 +248,7 @@ class cluster_options
246
248
  std::string password;
247
249
  std::string certificate_path;
248
250
  std::string key_path;
249
- std::vector<std::string> allowed_sasl_mechanisms;
251
+ std::optional<std::vector<std::string>> allowed_sasl_mechanisms;
250
252
  compression_options::built compression;
251
253
  timeout_options::built timeouts;
252
254
  dns_options::built dns;
@@ -261,15 +263,12 @@ class cluster_options
261
263
 
262
264
  [[nodiscard]] auto build() const -> built
263
265
  {
264
- static const std::vector<std::string> default_sasl_mechanisms{ "SCRAM-SHA512", "SCRAM-SHA256", "SCRAM-SHA1" };
265
- static const std::vector<std::string> ldap_sasl_mechanisms{ "PLAIN" };
266
-
267
266
  return {
268
267
  username_,
269
268
  password_,
270
269
  certificate_path_,
271
270
  key_path_,
272
- ldap_compatible_ ? ldap_sasl_mechanisms : default_sasl_mechanisms,
271
+ sasl_mechanisms_,
273
272
  compression_.build(),
274
273
  timeouts_.build(),
275
274
  dns_.build(),
@@ -288,7 +287,7 @@ class cluster_options
288
287
  std::string password_{};
289
288
  std::string certificate_path_{};
290
289
  std::string key_path_{};
291
- bool ldap_compatible_{ false };
290
+ std::optional<std::vector<std::string>> sasl_mechanisms_{};
292
291
 
293
292
  compression_options compression_{};
294
293
  timeout_options timeouts_{};
@@ -19,6 +19,7 @@
19
19
 
20
20
  #include <couchbase/binary_collection.hxx>
21
21
  #include <couchbase/codec/default_json_transcoder.hxx>
22
+ #include <couchbase/collection_query_index_manager.hxx>
22
23
  #include <couchbase/exists_options.hxx>
23
24
  #include <couchbase/expiry.hxx>
24
25
  #include <couchbase/get_all_replicas_options.hxx>
@@ -31,12 +32,14 @@
31
32
  #include <couchbase/lookup_in_specs.hxx>
32
33
  #include <couchbase/mutate_in_options.hxx>
33
34
  #include <couchbase/mutate_in_specs.hxx>
35
+ #include <couchbase/query_options.hxx>
34
36
  #include <couchbase/remove_options.hxx>
35
37
  #include <couchbase/replace_options.hxx>
36
38
  #include <couchbase/touch_options.hxx>
37
39
  #include <couchbase/unlock_options.hxx>
38
40
  #include <couchbase/upsert_options.hxx>
39
41
 
42
+ #include <fmt/format.h>
40
43
  #include <future>
41
44
  #include <memory>
42
45
 
@@ -991,6 +994,11 @@ class collection
991
994
  return future;
992
995
  }
993
996
 
997
+ [[nodiscard]] auto query_indexes() const -> collection_query_index_manager
998
+ {
999
+ return collection_query_index_manager(core_, bucket_name_, scope_name_, name_);
1000
+ }
1001
+
994
1002
  private:
995
1003
  friend class bucket;
996
1004
  friend class scope;