couchbase 4.2.1 → 4.2.2

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 (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;