couchbase 3.4.2 → 3.4.3

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 (241) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/couchbase/CMakeLists.txt +57 -7
  4. data/ext/couchbase/cmake/Documentation.cmake +0 -1
  5. data/ext/couchbase/cmake/OpenSSL.cmake +98 -3
  6. data/ext/couchbase/cmake/Testing.cmake +12 -4
  7. data/ext/couchbase/cmake/build_config.hxx.in +3 -0
  8. data/ext/couchbase/core/bucket.cxx +3 -2
  9. data/ext/couchbase/core/bucket.hxx +9 -0
  10. data/ext/couchbase/core/cluster.hxx +17 -0
  11. data/ext/couchbase/core/cluster_options.cxx +2 -2
  12. data/ext/couchbase/core/cluster_options.hxx +4 -6
  13. data/ext/couchbase/core/cluster_options_fwd.hxx +26 -0
  14. data/ext/couchbase/core/config_profile.hxx +1 -54
  15. data/ext/couchbase/core/config_profiles.cxx +79 -0
  16. data/ext/couchbase/core/config_profiles.hxx +56 -0
  17. data/ext/couchbase/core/error_context/search.hxx +1 -1
  18. data/ext/couchbase/core/impl/analytics.cxx +1 -0
  19. data/ext/couchbase/core/impl/boolean_field_query.cxx +40 -0
  20. data/ext/couchbase/core/impl/boolean_query.cxx +62 -0
  21. data/ext/couchbase/core/impl/cluster.cxx +2 -0
  22. data/ext/couchbase/core/impl/conjunction_query.cxx +51 -0
  23. data/ext/couchbase/core/impl/date_range.cxx +89 -0
  24. data/ext/couchbase/core/impl/date_range_facet.cxx +54 -0
  25. data/ext/couchbase/core/impl/date_range_facet_result.cxx +64 -0
  26. data/ext/couchbase/core/impl/date_range_query.cxx +125 -0
  27. data/ext/couchbase/core/impl/disjunction_query.cxx +51 -0
  28. data/ext/couchbase/core/impl/encoded_search_facet.hxx +29 -0
  29. data/ext/couchbase/core/impl/encoded_search_query.hxx +29 -0
  30. data/ext/couchbase/core/impl/encoded_search_sort.hxx +29 -0
  31. data/ext/couchbase/core/impl/geo_bounding_box_query.cxx +46 -0
  32. data/ext/couchbase/core/impl/geo_distance_query.cxx +43 -0
  33. data/ext/couchbase/core/impl/geo_polygon_query.cxx +46 -0
  34. data/ext/couchbase/core/impl/internal_date_range_facet_result.cxx +80 -0
  35. data/ext/couchbase/core/impl/internal_date_range_facet_result.hxx +48 -0
  36. data/ext/couchbase/core/impl/internal_numeric_range_facet_result.cxx +80 -0
  37. data/ext/couchbase/core/impl/internal_numeric_range_facet_result.hxx +48 -0
  38. data/ext/couchbase/core/impl/internal_search_error_context.cxx +141 -0
  39. data/ext/couchbase/core/impl/internal_search_error_context.hxx +61 -0
  40. data/ext/couchbase/core/impl/internal_search_meta_data.cxx +60 -0
  41. data/ext/couchbase/core/impl/internal_search_meta_data.hxx +41 -0
  42. data/ext/couchbase/core/impl/internal_search_result.cxx +84 -0
  43. data/ext/couchbase/core/impl/internal_search_result.hxx +43 -0
  44. data/ext/couchbase/core/impl/internal_search_row.cxx +82 -0
  45. data/ext/couchbase/core/impl/internal_search_row.hxx +56 -0
  46. data/ext/couchbase/core/impl/internal_search_row_location.hxx +32 -0
  47. data/ext/couchbase/core/impl/internal_search_row_locations.cxx +137 -0
  48. data/ext/couchbase/core/impl/internal_search_row_locations.hxx +45 -0
  49. data/ext/couchbase/core/impl/internal_term_facet_result.cxx +80 -0
  50. data/ext/couchbase/core/impl/internal_term_facet_result.hxx +48 -0
  51. data/ext/couchbase/core/impl/match_all_query.cxx +35 -0
  52. data/ext/couchbase/core/impl/match_none_query.cxx +35 -0
  53. data/ext/couchbase/core/impl/match_phrase_query.cxx +43 -0
  54. data/ext/couchbase/core/impl/match_query.cxx +59 -0
  55. data/ext/couchbase/core/impl/numeric_range.cxx +49 -0
  56. data/ext/couchbase/core/impl/numeric_range_facet.cxx +54 -0
  57. data/ext/couchbase/core/impl/numeric_range_facet_result.cxx +64 -0
  58. data/ext/couchbase/core/impl/numeric_range_query.cxx +56 -0
  59. data/ext/couchbase/core/impl/phrase_query.cxx +42 -0
  60. data/ext/couchbase/core/impl/prefix_query.cxx +40 -0
  61. data/ext/couchbase/core/impl/query_string_query.cxx +37 -0
  62. data/ext/couchbase/core/impl/regexp_query.cxx +40 -0
  63. data/ext/couchbase/core/impl/search.cxx +191 -0
  64. data/ext/couchbase/core/impl/search_error_context.cxx +147 -0
  65. data/ext/couchbase/core/impl/search_meta_data.cxx +46 -0
  66. data/ext/couchbase/core/impl/search_result.cxx +66 -0
  67. data/ext/couchbase/core/impl/search_row.cxx +74 -0
  68. data/ext/couchbase/core/impl/search_row_location.cxx +64 -0
  69. data/ext/couchbase/core/impl/search_row_locations.cxx +66 -0
  70. data/ext/couchbase/core/impl/search_sort_field.cxx +104 -0
  71. data/ext/couchbase/core/impl/search_sort_id.cxx +43 -0
  72. data/ext/couchbase/core/impl/search_sort_score.cxx +43 -0
  73. data/ext/couchbase/core/impl/term_facet.cxx +36 -0
  74. data/ext/couchbase/core/impl/term_facet_result.cxx +64 -0
  75. data/ext/couchbase/core/impl/term_query.cxx +56 -0
  76. data/ext/couchbase/core/impl/term_range_query.cxx +57 -0
  77. data/ext/couchbase/core/impl/wildcard_query.cxx +40 -0
  78. data/ext/couchbase/core/io/http_context.hxx +1 -1
  79. data/ext/couchbase/core/io/http_session.hxx +10 -0
  80. data/ext/couchbase/core/io/http_session_manager.hxx +5 -3
  81. data/ext/couchbase/core/io/mcbp_session.cxx +28 -1
  82. data/ext/couchbase/core/io/retry_orchestrator.hxx +3 -2
  83. data/ext/couchbase/core/json_string.hxx +5 -0
  84. data/ext/couchbase/core/meta/version.cxx +18 -4
  85. data/ext/couchbase/core/mozilla_ca_bundle.hxx +39 -0
  86. data/ext/couchbase/core/operations/document_analytics.cxx +1 -0
  87. data/ext/couchbase/core/operations/document_analytics.hxx +1 -0
  88. data/ext/couchbase/core/operations/document_append.hxx +1 -1
  89. data/ext/couchbase/core/operations/document_decrement.hxx +1 -1
  90. data/ext/couchbase/core/operations/document_exists.hxx +1 -1
  91. data/ext/couchbase/core/operations/document_get.hxx +1 -1
  92. data/ext/couchbase/core/operations/document_get_and_lock.hxx +1 -1
  93. data/ext/couchbase/core/operations/document_get_and_touch.hxx +1 -1
  94. data/ext/couchbase/core/operations/document_get_projected.hxx +1 -1
  95. data/ext/couchbase/core/operations/document_increment.hxx +1 -1
  96. data/ext/couchbase/core/operations/document_insert.hxx +1 -1
  97. data/ext/couchbase/core/operations/document_lookup_in.hxx +1 -1
  98. data/ext/couchbase/core/operations/document_mutate_in.hxx +1 -1
  99. data/ext/couchbase/core/operations/document_prepend.hxx +1 -1
  100. data/ext/couchbase/core/operations/document_query.cxx +2 -0
  101. data/ext/couchbase/core/operations/document_query.hxx +6 -0
  102. data/ext/couchbase/core/operations/document_remove.hxx +1 -1
  103. data/ext/couchbase/core/operations/document_replace.hxx +1 -1
  104. data/ext/couchbase/core/operations/document_search.cxx +4 -1
  105. data/ext/couchbase/core/operations/document_search.hxx +2 -1
  106. data/ext/couchbase/core/operations/document_touch.hxx +1 -1
  107. data/ext/couchbase/core/operations/document_unlock.hxx +1 -1
  108. data/ext/couchbase/core/operations/document_upsert.hxx +1 -1
  109. data/ext/couchbase/core/operations/document_view.hxx +1 -0
  110. data/ext/couchbase/core/protocol/client_request.hxx +11 -2
  111. data/ext/couchbase/core/public_fwd.hxx +21 -0
  112. data/ext/couchbase/core/tls_verify_mode.hxx +26 -0
  113. data/ext/couchbase/core/topology/configuration.cxx +15 -2
  114. data/ext/couchbase/core/topology/configuration.hxx +5 -1
  115. data/ext/couchbase/core/transactions/attempt_context_testing_hooks.cxx +93 -0
  116. data/ext/couchbase/core/transactions/attempt_context_testing_hooks.hxx +48 -75
  117. data/ext/couchbase/core/transactions/cleanup_testing_hooks.cxx +52 -0
  118. data/ext/couchbase/core/transactions/cleanup_testing_hooks.hxx +17 -31
  119. data/ext/couchbase/core/transactions/exceptions.hxx +12 -9
  120. data/ext/couchbase/core/utils/connection_string.cxx +17 -0
  121. data/ext/couchbase/core/utils/json.cxx +4 -1
  122. data/ext/couchbase/couchbase/behavior_options.hxx +10 -1
  123. data/ext/couchbase/couchbase/boolean_field_query.hxx +77 -0
  124. data/ext/couchbase/couchbase/boolean_query.hxx +223 -0
  125. data/ext/couchbase/couchbase/cluster.hxx +42 -1
  126. data/ext/couchbase/couchbase/conjunction_query.hxx +88 -0
  127. data/ext/couchbase/couchbase/date_range.hxx +69 -0
  128. data/ext/couchbase/couchbase/date_range_facet.hxx +56 -0
  129. data/ext/couchbase/couchbase/date_range_facet_result.hxx +55 -0
  130. data/ext/couchbase/couchbase/date_range_query.hxx +265 -0
  131. data/ext/couchbase/couchbase/disjunction_query.hxx +109 -0
  132. data/ext/couchbase/couchbase/doc_id_query.hxx +111 -0
  133. data/ext/couchbase/couchbase/error_context.hxx +7 -6
  134. data/ext/couchbase/couchbase/fmt/analytics_scan_consistency.hxx +52 -0
  135. data/ext/couchbase/couchbase/fmt/search_scan_consistency.hxx +49 -0
  136. data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +107 -0
  137. data/ext/couchbase/couchbase/geo_distance_query.hxx +109 -0
  138. data/ext/couchbase/couchbase/geo_point.hxx +32 -0
  139. data/ext/couchbase/couchbase/geo_polygon_query.hxx +85 -0
  140. data/ext/couchbase/couchbase/highlight_style.hxx +45 -0
  141. data/ext/couchbase/couchbase/match_all_query.hxx +43 -0
  142. data/ext/couchbase/couchbase/match_none_query.hxx +43 -0
  143. data/ext/couchbase/couchbase/match_operator.hxx +45 -0
  144. data/ext/couchbase/couchbase/match_phrase_query.hxx +108 -0
  145. data/ext/couchbase/couchbase/match_query.hxx +163 -0
  146. data/ext/couchbase/couchbase/numeric_range.hxx +58 -0
  147. data/ext/couchbase/couchbase/numeric_range_facet.hxx +56 -0
  148. data/ext/couchbase/couchbase/numeric_range_facet_result.hxx +55 -0
  149. data/ext/couchbase/couchbase/numeric_range_query.hxx +143 -0
  150. data/ext/couchbase/couchbase/phrase_query.hxx +93 -0
  151. data/ext/couchbase/couchbase/prefix_query.hxx +82 -0
  152. data/ext/couchbase/couchbase/query_string_query.hxx +72 -0
  153. data/ext/couchbase/couchbase/regexp_query.hxx +82 -0
  154. data/ext/couchbase/couchbase/scope.hxx +40 -0
  155. data/ext/couchbase/couchbase/search_date_range.hxx +68 -0
  156. data/ext/couchbase/couchbase/search_error_context.hxx +138 -0
  157. data/ext/couchbase/couchbase/search_facet.hxx +60 -0
  158. data/ext/couchbase/couchbase/search_facet_result.hxx +50 -0
  159. data/ext/couchbase/couchbase/search_meta_data.hxx +85 -0
  160. data/ext/couchbase/couchbase/search_metrics.hxx +127 -0
  161. data/ext/couchbase/couchbase/search_numeric_range.hxx +69 -0
  162. data/ext/couchbase/couchbase/search_options.hxx +509 -0
  163. data/ext/couchbase/couchbase/search_query.hxx +69 -0
  164. data/ext/couchbase/couchbase/search_result.hxx +77 -0
  165. data/ext/couchbase/couchbase/search_row.hxx +104 -0
  166. data/ext/couchbase/couchbase/search_row_location.hxx +55 -0
  167. data/ext/couchbase/couchbase/search_row_locations.hxx +86 -0
  168. data/ext/couchbase/couchbase/search_scan_consistency.hxx +34 -0
  169. data/ext/couchbase/couchbase/search_sort.hxx +58 -0
  170. data/ext/couchbase/couchbase/search_sort_field.hxx +117 -0
  171. data/ext/couchbase/couchbase/search_sort_field_missing.hxx +26 -0
  172. data/ext/couchbase/couchbase/search_sort_field_mode.hxx +27 -0
  173. data/ext/couchbase/couchbase/search_sort_field_type.hxx +28 -0
  174. data/ext/couchbase/couchbase/search_sort_id.hxx +60 -0
  175. data/ext/couchbase/couchbase/search_sort_score.hxx +60 -0
  176. data/ext/couchbase/couchbase/search_term_range.hxx +51 -0
  177. data/ext/couchbase/couchbase/security_options.hxx +3 -0
  178. data/ext/couchbase/couchbase/term_facet.hxx +48 -0
  179. data/ext/couchbase/couchbase/term_facet_result.hxx +55 -0
  180. data/ext/couchbase/couchbase/term_query.hxx +151 -0
  181. data/ext/couchbase/couchbase/term_range_query.hxx +142 -0
  182. data/ext/couchbase/couchbase/tracing/request_span.hxx +63 -0
  183. data/ext/couchbase/couchbase/tracing/request_tracer.hxx +2 -40
  184. data/ext/couchbase/couchbase/transactions/async_attempt_context.hxx +83 -4
  185. data/ext/couchbase/couchbase/transactions/attempt_context.hxx +67 -0
  186. data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +2 -0
  187. data/ext/couchbase/couchbase/transactions/transaction_keyspace.hxx +11 -1
  188. data/ext/couchbase/couchbase/transactions/transaction_options.hxx +79 -8
  189. data/ext/couchbase/couchbase/transactions/transaction_query_options.hxx +128 -15
  190. data/ext/couchbase/couchbase/transactions/transaction_query_result.hxx +4 -0
  191. data/ext/couchbase/couchbase/transactions/transaction_result.hxx +1 -1
  192. data/ext/couchbase/couchbase/transactions/transactions_cleanup_config.hxx +5 -3
  193. data/ext/couchbase/couchbase/transactions/transactions_config.hxx +9 -5
  194. data/ext/couchbase/couchbase/transactions/transactions_query_config.hxx +6 -3
  195. data/ext/couchbase/couchbase/transactions.hxx +34 -1
  196. data/ext/couchbase/couchbase/wildcard_query.hxx +83 -0
  197. data/ext/couchbase/test/CMakeLists.txt +7 -5
  198. data/ext/couchbase/test/benchmark_helper_integration.hxx +2 -2
  199. data/ext/couchbase/test/test_helper.hxx +5 -5
  200. data/ext/couchbase/test/test_integration_analytics.cxx +28 -6
  201. data/ext/couchbase/test/test_integration_collections.cxx +7 -3
  202. data/ext/couchbase/test/test_integration_connect.cxx +7 -3
  203. data/ext/couchbase/test/test_integration_crud.cxx +13 -3
  204. data/ext/couchbase/test/test_integration_diagnostics.cxx +11 -5
  205. data/ext/couchbase/test/test_integration_durability.cxx +12 -7
  206. data/ext/couchbase/test/test_integration_examples.cxx +283 -11
  207. data/ext/couchbase/test/test_integration_management.cxx +147 -91
  208. data/ext/couchbase/test/test_integration_query.cxx +68 -10
  209. data/ext/couchbase/test/test_integration_range_scan.cxx +12 -12
  210. data/ext/couchbase/test/test_integration_read_replica.cxx +48 -11
  211. data/ext/couchbase/test/test_integration_search.cxx +22 -2
  212. data/ext/couchbase/test/test_integration_subdoc.cxx +62 -11
  213. data/ext/couchbase/test/test_integration_tracer.cxx +5 -0
  214. data/ext/couchbase/test/test_integration_transcoders.cxx +13 -5
  215. data/ext/couchbase/test/{test_transaction_transaction_context.cxx → test_transaction_context.cxx} +1 -1
  216. data/ext/couchbase/test/test_transaction_examples.cxx +195 -0
  217. data/ext/couchbase/test/{test_transaction_transaction_simple.cxx → test_transaction_simple.cxx} +17 -5
  218. data/ext/couchbase/test/{test_transaction_transaction_simple_async.cxx → test_transaction_simple_async.cxx} +19 -21
  219. data/ext/couchbase/test/test_unit_config_profiles.cxx +1 -1
  220. data/ext/couchbase/test/test_unit_json_transcoder.cxx +4 -0
  221. data/ext/couchbase/test/test_unit_search.cxx +427 -0
  222. data/ext/couchbase/test/test_unit_transaction_utils.cxx +10 -1
  223. data/ext/couchbase/test/test_unit_utils.cxx +8 -4
  224. data/ext/couchbase.cxx +58 -16
  225. data/ext/revisions.rb +3 -3
  226. data/lib/couchbase/authenticator.rb +0 -1
  227. data/lib/couchbase/cluster.rb +0 -4
  228. data/lib/couchbase/config_profiles.rb +1 -1
  229. data/lib/couchbase/json_transcoder.rb +12 -5
  230. data/lib/couchbase/management/collection_query_index_manager.rb +54 -15
  231. data/lib/couchbase/management/query_index_manager.rb +70 -5
  232. data/lib/couchbase/raw_binary_transcoder.rb +37 -0
  233. data/lib/couchbase/raw_json_transcoder.rb +38 -0
  234. data/lib/couchbase/raw_string_transcoder.rb +40 -0
  235. data/lib/couchbase/search_options.rb +5 -0
  236. data/lib/couchbase/transcoder_flags.rb +62 -0
  237. data/lib/couchbase/version.rb +1 -1
  238. metadata +139 -11
  239. data/ext/couchbase/core/config_profile.cxx +0 -47
  240. /data/ext/couchbase/test/{test_transaction_transaction_public_async_api.cxx → test_transaction_public_async_api.cxx} +0 -0
  241. /data/ext/couchbase/test/{test_transaction_transaction_public_blocking_api.cxx → test_transaction_public_blocking_api.cxx} +0 -0
@@ -25,7 +25,7 @@ TEST_CASE("integration: missing scope and collection", "[integration]")
25
25
  test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
26
26
 
27
27
  if (!integration.cluster_version().supports_collections()) {
28
- return;
28
+ SKIP("cluster does not support collections");
29
29
  }
30
30
 
31
31
  SECTION("get missing scope")
@@ -77,7 +77,7 @@ TEST_CASE("integration: get and insert non default scope and collection", "[inte
77
77
  test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
78
78
 
79
79
  if (!integration.cluster_version().supports_collections()) {
80
- return;
80
+ SKIP("cluster does not support collections");
81
81
  }
82
82
 
83
83
  auto scope_name = test::utils::uniq_id("scope");
@@ -121,7 +121,7 @@ TEST_CASE("integration: insert into dropped scope", "[integration]")
121
121
  test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
122
122
 
123
123
  if (!integration.cluster_version().supports_collections()) {
124
- return;
124
+ SKIP("cluster does not support collections");
125
125
  }
126
126
 
127
127
  auto scope_name = test::utils::uniq_id("scope");
@@ -166,6 +166,10 @@ TEST_CASE("integration: insert into dropped scope", "[integration]")
166
166
  REQUIRE(dropped);
167
167
  }
168
168
 
169
+ if (integration.cluster_version().is_mock()) {
170
+ SKIP("GOCAVES does not generate error when inserting into dropped collection. See "
171
+ "https://github.com/couchbaselabs/gocaves/issues/108");
172
+ }
169
173
  {
170
174
  couchbase::core::operations::upsert_request req{ id, couchbase::core::utils::to_binary(key) };
171
175
  auto resp = test::utils::execute(integration.cluster, req);
@@ -42,9 +42,9 @@ TEST_CASE("integration: connecting with unresponsive first node in bootstrap nod
42
42
  test::utils::init_logger();
43
43
  asio::io_context io{};
44
44
  auto ctx = test::utils::test_context::load_from_environment();
45
- if (ctx.deployment == test::utils::deployment_type::capella) {
45
+ if (ctx.deployment == test::utils::deployment_type::capella || ctx.deployment == test::utils::deployment_type::elixir) {
46
46
  // This breaks SRV assumptions (only one host in connection string)
47
- return;
47
+ SKIP("capella deployment uses single host in the connection string, which assumed to be reachable");
48
48
  }
49
49
  auto connstr = couchbase::core::utils::parse_connection_string(ctx.connection_string);
50
50
  REQUIRE_FALSE(connstr.bootstrap_nodes.empty());
@@ -125,6 +125,10 @@ TEST_CASE("integration: destroy cluster without waiting for close completion", "
125
125
  test::utils::init_logger();
126
126
  auto ctx = test::utils::test_context::load_from_environment();
127
127
 
128
+ if (ctx.deployment == test::utils::deployment_type::elixir) {
129
+ SKIP("elixir deployment is incompatible with parts of this test, but it is probably bug in SDK. FIXME");
130
+ }
131
+
128
132
  asio::io_context io{};
129
133
 
130
134
  auto cluster = couchbase::core::cluster::create(io);
@@ -143,7 +147,7 @@ TEST_CASE("integration: destroy cluster without waiting for close completion", "
143
147
  }
144
148
 
145
149
  // hit Query
146
- {
150
+ if (ctx.version.supports_query()) {
147
151
  couchbase::core::operations::query_request req{ R"(SELECT 42 AS the_answer)" };
148
152
  auto resp = test::utils::execute(cluster, req);
149
153
  REQUIRE_SUCCESS(resp.ctx.ec);
@@ -35,6 +35,10 @@ TEST_CASE("integration: switching off mutation token", "[integration]")
35
35
  opts.enable_mutation_tokens = false;
36
36
  test::utils::integration_test_guard integration(opts);
37
37
 
38
+ if (integration.cluster_version().is_mock()) {
39
+ SKIP("GOCAVES does not allow to switching off mutation tokens. See https://github.com/couchbaselabs/gocaves/issues/100");
40
+ }
41
+
38
42
  test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
39
43
  couchbase::core::document_id id{ integration.ctx.bucket, "_default", "_default", test::utils::uniq_id("foo") };
40
44
 
@@ -228,7 +232,8 @@ TEST_CASE("integration: pessimistic locking", "[integration]")
228
232
  {
229
233
  couchbase::core::operations::get_and_lock_request req{ id };
230
234
  req.lock_time = lock_time;
231
- if (integration.ctx.deployment == test::utils::deployment_type::capella) {
235
+ if (integration.ctx.deployment == test::utils::deployment_type::capella ||
236
+ integration.ctx.deployment == test::utils::deployment_type::elixir) {
232
237
  req.timeout = std::chrono::seconds{ 2 };
233
238
  }
234
239
  auto resp = test::utils::execute(integration.cluster, req);
@@ -489,7 +494,7 @@ TEST_CASE("integration: upsert preserve expiry", "[integration]")
489
494
  test::utils::integration_test_guard integration;
490
495
 
491
496
  if (!integration.cluster_version().supports_preserve_expiry()) {
492
- return;
497
+ SKIP("cluster does not support preserve expiry");
493
498
  }
494
499
 
495
500
  test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
@@ -670,6 +675,10 @@ TEST_CASE("integration: open bucket that does not exist", "[integration]")
670
675
  {
671
676
  test::utils::integration_test_guard integration;
672
677
 
678
+ if (integration.cluster_version().is_mock()) {
679
+ SKIP("GOCAVES returns not_found (0x01) instead of no_access (0x24). See https://github.com/couchbaselabs/gocaves/issues/102");
680
+ }
681
+
673
682
  auto bucket_name = test::utils::uniq_id("missing_bucket");
674
683
 
675
684
  auto barrier = std::make_shared<std::promise<std::error_code>>();
@@ -814,7 +823,8 @@ TEST_CASE("integration: pessimistic locking with public API", "[integration]")
814
823
  // it is not allowed to lock the same key twice
815
824
  {
816
825
  couchbase::get_and_lock_options options{};
817
- if (integration.ctx.deployment == test::utils::deployment_type::capella) {
826
+ if (integration.ctx.deployment == test::utils::deployment_type::capella ||
827
+ integration.ctx.deployment == test::utils::deployment_type::elixir) {
818
828
  options.timeout(std::chrono::seconds{ 2 });
819
829
  }
820
830
  auto [ctx, resp] = collection.get_and_lock(id, lock_time, options).get();
@@ -321,14 +321,18 @@ TEST_CASE("integration: fetch diagnostics after N1QL query", "[integration]")
321
321
  {
322
322
  test::utils::integration_test_guard integration;
323
323
 
324
+ if (!integration.cluster_version().supports_query() || integration.ctx.deployment == test::utils::deployment_type::elixir) {
325
+ SKIP("cluster does not support query or cluster level query");
326
+ }
327
+
324
328
  test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
325
329
  {
326
330
  couchbase::core::operations::query_request req{ "SELECT 'hello, couchbase' AS greetings" };
327
331
  auto resp = test::utils::execute(integration.cluster, req);
328
332
  REQUIRE_SUCCESS(resp.ctx.ec);
329
- INFO("rows.size() =" << resp.rows.size())
333
+ INFO("rows.size() =" << resp.rows.size());
330
334
  REQUIRE(resp.rows.size() == 1);
331
- INFO("row=" << resp.rows[0])
335
+ INFO("row=" << resp.rows[0]);
332
336
  REQUIRE(resp.rows[0] == R"({"greetings":"hello, couchbase"})");
333
337
  }
334
338
  {
@@ -365,8 +369,10 @@ TEST_CASE("integration: ping", "[integration]")
365
369
  REQUIRE(res.services.count(couchbase::core::service_type::management) > 0);
366
370
  REQUIRE(res.services[couchbase::core::service_type::management].size() > 0);
367
371
 
368
- REQUIRE(res.services.count(couchbase::core::service_type::view) > 0);
369
- REQUIRE(res.services[couchbase::core::service_type::view].size() > 0);
372
+ if (integration.ctx.deployment != test::utils::deployment_type::elixir) {
373
+ REQUIRE(res.services.count(couchbase::core::service_type::view) > 0);
374
+ REQUIRE(res.services[couchbase::core::service_type::view].size() > 0);
375
+ }
370
376
 
371
377
  REQUIRE(res.services.count(couchbase::core::service_type::query) > 0);
372
378
  REQUIRE(res.services[couchbase::core::service_type::query].size() > 0);
@@ -385,7 +391,7 @@ TEST_CASE("integration: ping", "[integration]")
385
391
  }
386
392
 
387
393
  REQUIRE(res.id == "my_report_id");
388
- INFO(res.sdk)
394
+ INFO(res.sdk);
389
395
  REQUIRE(res.sdk.find("cxx/") == 0);
390
396
  }
391
397
  }
@@ -25,7 +25,7 @@ TEST_CASE("integration: durable operations", "[integration]")
25
25
  {
26
26
  test::utils::integration_test_guard integration;
27
27
  if (!integration.cluster_version().supports_enhanced_durability()) {
28
- return;
28
+ SKIP("cluster does not support enhanced durability");
29
29
  }
30
30
 
31
31
  test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
@@ -68,7 +68,7 @@ TEST_CASE("integration: durable operations", "[integration]")
68
68
  auto resp = test::utils::execute(integration.cluster, req);
69
69
  REQUIRE_SUCCESS(resp.ctx.ec());
70
70
  REQUIRE(!resp.cas.empty());
71
- REQUIRE(resp.value == couchbase::core::utils::to_binary(R"({"foo":"bar","baz":42})"));
71
+ REQUIRE(couchbase::core::utils::json::parse_binary(resp.value) == couchbase::core::utils::json::parse(R"({"foo":"bar","baz":42})"));
72
72
  }
73
73
  {
74
74
  couchbase::core::operations::remove_request req{ id };
@@ -83,8 +83,13 @@ TEST_CASE("integration: durable operations", "[integration]")
83
83
  TEST_CASE("integration: legacy durability persist to active and replicate to one", "[integration]")
84
84
  {
85
85
  test::utils::integration_test_guard integration;
86
- if (integration.number_of_replicas() == 0 || integration.number_of_nodes() <= integration.number_of_replicas()) {
87
- return;
86
+ if (integration.number_of_replicas() == 0) {
87
+ SKIP("bucket has zero replicas");
88
+ }
89
+ if (integration.number_of_nodes() <= integration.number_of_replicas()) {
90
+ SKIP(fmt::format("number of nodes ({}) is less or equal to number of replicas ({})",
91
+ integration.number_of_nodes(),
92
+ integration.number_of_replicas()));
88
93
  }
89
94
 
90
95
  test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
@@ -124,7 +129,7 @@ TEST_CASE("integration: low level legacy durability impossible if number of node
124
129
  test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
125
130
 
126
131
  if (integration.number_of_replicas() == 3) {
127
- return;
132
+ SKIP("bucket has three replicas configured, so the test will not be applicable");
128
133
  }
129
134
 
130
135
  couchbase::core::document_id id{ integration.ctx.bucket, "_default", "_default", test::utils::uniq_id("foo") };
@@ -159,7 +164,7 @@ TEST_CASE("integration: low level legacy durability persist to active and replic
159
164
  test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
160
165
 
161
166
  if (integration.number_of_replicas() < 1) {
162
- return;
167
+ SKIP("bucket does not have replicas configured");
163
168
  }
164
169
 
165
170
  couchbase::core::document_id id{ integration.ctx.bucket, "_default", "_default", test::utils::uniq_id("foo") };
@@ -211,7 +216,7 @@ TEST_CASE("integration: low level legacy durability persist to active and replic
211
216
  auto resp = test::utils::execute(integration.cluster, req);
212
217
  REQUIRE_SUCCESS(resp.ctx.ec());
213
218
  REQUIRE(!resp.cas.empty());
214
- REQUIRE(resp.value == couchbase::core::utils::to_binary(R"({"foo":"bar","baz":42})"));
219
+ REQUIRE(couchbase::core::utils::json::parse_binary(resp.value) == couchbase::core::utils::json::parse(R"({"foo":"bar","baz":42})"));
215
220
  }
216
221
  {
217
222
  couchbase::core::operations::remove_request_with_legacy_durability req{
@@ -21,9 +21,14 @@
21
21
  #include "core/operations/management/query_index_create.hxx"
22
22
  #include "core/operations/management/query_index_get_all.hxx"
23
23
 
24
+ #include <couchbase/boolean_query.hxx>
24
25
  #include <couchbase/cluster.hxx>
25
26
  #include <couchbase/fmt/cas.hxx>
26
27
  #include <couchbase/fmt/mutation_token.hxx>
28
+ #include <couchbase/match_query.hxx>
29
+ #include <couchbase/numeric_range_query.hxx>
30
+ #include <couchbase/query_string_query.hxx>
31
+ #include <couchbase/term_facet.hxx>
27
32
 
28
33
  #include <tao/json.hpp>
29
34
 
@@ -44,9 +49,9 @@ main(int argc, const char* argv[])
44
49
  return 1;
45
50
  }
46
51
 
47
- std::string connection_string{ argv[1] };
48
- std::string username{ argv[2] };
49
- std::string password{ argv[3] };
52
+ std::string connection_string{ argv[1] }; // "couchbase://127.0.0.1"
53
+ std::string username{ argv[2] }; // "Administrator"
54
+ std::string password{ argv[3] }; // "password"
50
55
  std::string bucket_name{ "travel-sample" };
51
56
 
52
57
  // run IO context on separate thread
@@ -59,6 +64,7 @@ main(int argc, const char* argv[])
59
64
  // For example, optimize timeouts for WAN
60
65
  options.apply_profile("wan_development");
61
66
 
67
+ // [1] connect to cluster using the given connection string and the options
62
68
  auto [cluster, ec] = couchbase::cluster::connect(io, connection_string, options).get();
63
69
  if (ec) {
64
70
  fmt::print("unable to connect to the cluster: {}\n", ec.message());
@@ -72,8 +78,7 @@ main(int argc, const char* argv[])
72
78
  auto scope = bucket.scope("tenant_agent_00");
73
79
  auto collection = scope.collection("users");
74
80
 
75
- {
76
- // upsert document
81
+ { // [2] upsert document
77
82
  auto [ctx, upsert_result] = collection.upsert("my-document", tao::json::value{ { "name", "mike" } }).get();
78
83
  if (ctx.ec()) {
79
84
  fmt::print("unable to upsert the document \"{}\": {}\n", ctx.id(), ctx.ec().message());
@@ -82,8 +87,7 @@ main(int argc, const char* argv[])
82
87
  fmt::print("saved document \"{}\", cas={}, token={}\n", ctx.id(), upsert_result.cas(), upsert_result.mutation_token().value());
83
88
  }
84
89
 
85
- {
86
- // get document
90
+ { // [3] get document
87
91
  auto [ctx, get_result] = collection.get("my-document").get();
88
92
  if (ctx.ec()) {
89
93
  fmt::print("unable to get the document \"{}\": {}\n", ctx.id(), ctx.ec().message());
@@ -93,8 +97,7 @@ main(int argc, const char* argv[])
93
97
  fmt::print("retrieved document \"{}\", name=\"{}\"\n", ctx.id(), name);
94
98
  }
95
99
 
96
- {
97
- // N1QL query
100
+ { // [4] N1QL query
98
101
  auto inventory_scope = bucket.scope("inventory");
99
102
  auto [ctx, query_result] = inventory_scope.query("SELECT * FROM airline WHERE id = 10").get();
100
103
  if (ctx.ec()) {
@@ -106,7 +109,7 @@ main(int argc, const char* argv[])
106
109
  }
107
110
  }
108
111
 
109
- // close cluster connection
112
+ // [5] close cluster connection
110
113
  cluster.close();
111
114
  guard.reset();
112
115
 
@@ -130,7 +133,10 @@ TEST_CASE("example: start using", "[integration]")
130
133
  {
131
134
  test::utils::integration_test_guard integration;
132
135
  if (!integration.cluster_version().supports_collections()) {
133
- return;
136
+ SKIP("cluster does not support collections");
137
+ }
138
+ if (integration.cluster_version().is_mock()) {
139
+ SKIP("GOCAVES cannot load travel-sample bucket. See https://github.com/couchbaselabs/gocaves/issues/101");
134
140
  }
135
141
 
136
142
  {
@@ -180,3 +186,269 @@ TEST_CASE("example: start using", "[integration]")
180
186
 
181
187
  REQUIRE(start_using::main(4, argv) == 0);
182
188
  }
189
+
190
+ namespace example_search
191
+ {
192
+ //! [example-search]
193
+ #include <couchbase/cluster.hxx>
194
+
195
+ #include <couchbase/boolean_query.hxx>
196
+ #include <couchbase/match_query.hxx>
197
+ #include <couchbase/numeric_range_query.hxx>
198
+ #include <couchbase/query_string_query.hxx>
199
+
200
+ #include <couchbase/fmt/cas.hxx>
201
+ #include <couchbase/fmt/mutation_token.hxx>
202
+
203
+ #include <tao/json.hpp>
204
+
205
+ int
206
+ main(int argc, const char* argv[])
207
+ {
208
+ if (argc != 4) {
209
+ fmt::print("USAGE: ./example_search couchbase://127.0.0.1 Administrator password\n");
210
+ return 1;
211
+ }
212
+
213
+ std::string connection_string{ argv[1] }; // "couchbase://127.0.0.1"
214
+ std::string username{ argv[2] }; // "Administrator"
215
+ std::string password{ argv[3] }; // "password"
216
+ std::string bucket_name{ "travel-sample" };
217
+
218
+ // run IO context on separate thread
219
+ asio::io_context io;
220
+ auto guard = asio::make_work_guard(io);
221
+ std::thread io_thread([&io]() { io.run(); });
222
+
223
+ auto options = couchbase::cluster_options(username, password);
224
+ // customize through the 'options'.
225
+ // For example, optimize timeouts for WAN
226
+ options.apply_profile("wan_development");
227
+
228
+ auto [cluster, ec] = couchbase::cluster::connect(io, connection_string, options).get();
229
+ if (ec) {
230
+ fmt::print("unable to connect to the cluster: {}\n", ec.message());
231
+ return 1;
232
+ }
233
+
234
+ {
235
+ fmt::print("--- simple query\n");
236
+ auto [ctx, result] = cluster.search_query("travel-sample-index", couchbase::query_string_query("nice bar")).get();
237
+
238
+ if (ctx.ec()) {
239
+ fmt::print("unable to perform search query: {}, ({}, {})\n", ctx.ec().message(), ctx.status(), ctx.error());
240
+ return 1;
241
+ }
242
+ fmt::print("{} hits, total: {}\n", result.rows().size(), result.meta_data().metrics().total_rows());
243
+ for (const auto& row : result.rows()) {
244
+ fmt::print("id: {}, score: {}\n", row.id(), row.score());
245
+ }
246
+ }
247
+
248
+ {
249
+ fmt::print("--- simple query with fields\n");
250
+ auto [ctx, result] = cluster
251
+ .search_query("travel-sample-index",
252
+ couchbase::query_string_query("nice bar"),
253
+ couchbase::search_options{}.fields({ "description" }))
254
+ .get();
255
+
256
+ if (ctx.ec()) {
257
+ fmt::print("unable to perform search query: {}, ({}, {})\n", ctx.ec().message(), ctx.status(), ctx.error());
258
+ return 1;
259
+ }
260
+ fmt::print("{} hits, total: {}\n", result.rows().size(), result.meta_data().metrics().total_rows());
261
+ for (const auto& row : result.rows()) {
262
+ auto fields = row.fields_as<couchbase::codec::tao_json_serializer>();
263
+ fmt::print("id: {}, score: {}, description: {}\n", row.id(), row.score(), fields["description"].as<std::string>());
264
+ }
265
+ }
266
+
267
+ {
268
+ fmt::print("--- simple query with limit\n");
269
+ auto [ctx, result] =
270
+ cluster
271
+ .search_query("travel-sample-index", couchbase::query_string_query("nice bar"), couchbase::search_options{}.skip(3).limit(4))
272
+ .get();
273
+
274
+ if (ctx.ec()) {
275
+ fmt::print("unable to perform search query: {}, ({}, {})\n", ctx.ec().message(), ctx.status(), ctx.error());
276
+ return 1;
277
+ }
278
+ fmt::print("{} hits, total: {}\n", result.rows().size(), result.meta_data().metrics().total_rows());
279
+ for (const auto& row : result.rows()) {
280
+ fmt::print("id: {}, score: {}\n", row.id(), row.score());
281
+ }
282
+ }
283
+
284
+ {
285
+ fmt::print("--- simple query with highlight\n");
286
+ auto [ctx, result] =
287
+ cluster
288
+ .search_query("travel-sample-index",
289
+ couchbase::query_string_query("nice bar"),
290
+ couchbase::search_options{}.highlight(couchbase::highlight_style::html, { "description", "title" }))
291
+ .get();
292
+
293
+ if (ctx.ec()) {
294
+ fmt::print("unable to perform search query: {}, ({}, {})\n", ctx.ec().message(), ctx.status(), ctx.error());
295
+ return 1;
296
+ }
297
+ fmt::print("{} hits, total: {}\n", result.rows().size(), result.meta_data().metrics().total_rows());
298
+ for (const auto& row : result.rows()) {
299
+ fmt::print("id: {}, score: {}\n", row.id(), row.score());
300
+ for (const auto& [field, fragments] : row.fragments()) {
301
+ fmt::print("- {}:\n", field);
302
+ for (const auto& fragment : fragments) {
303
+ fmt::print("-- {}\n", fragment);
304
+ }
305
+ }
306
+ }
307
+ }
308
+
309
+ {
310
+ fmt::print("--- simple query with collections\n");
311
+ auto [ctx, result] = cluster
312
+ .search_query("travel-sample-index",
313
+ couchbase::query_string_query("west"),
314
+ couchbase::search_options{}.collections({ "airline" }))
315
+ .get();
316
+
317
+ if (ctx.ec()) {
318
+ fmt::print("unable to perform search query: {}, ({}, {})\n", ctx.ec().message(), ctx.status(), ctx.error());
319
+ return 1;
320
+ }
321
+ fmt::print("{} hits, total: {}\n", result.rows().size(), result.meta_data().metrics().total_rows());
322
+ for (const auto& row : result.rows()) {
323
+ fmt::print("id: {}, score: {}\n", row.id(), row.score());
324
+ }
325
+ }
326
+
327
+ {
328
+ fmt::print("--- query with consistency requirements\n");
329
+
330
+ auto bucket = cluster.bucket(bucket_name);
331
+ auto collection = bucket.scope("inventory").collection("hotel");
332
+
333
+ couchbase::mutation_state state;
334
+
335
+ {
336
+ auto [ctx, upsert_result] =
337
+ collection
338
+ .upsert(
339
+ "prancing-pony",
340
+ tao::json::value{
341
+ { "title", "The Prancing Pony" },
342
+ { "type", "hotel" },
343
+ { "description",
344
+ "The inn was located just where the East Road bent round the foot of Bree-hill, within the dike that stretched "
345
+ "around the town. The building was three stories tall with many windows. Its front faced the Road and it had two "
346
+ "wings that ran back towards the elevated ground of the hill, such that in the rear the second floor was at ground "
347
+ "level. " } })
348
+ .get();
349
+ if (ctx.ec()) {
350
+ fmt::print("unable to upsert the document \"{}\": {}\n", ctx.id(), ctx.ec().message());
351
+ return 1;
352
+ }
353
+ fmt::print("saved document \"{}\", cas={}, token={}\n",
354
+ ctx.id(),
355
+ upsert_result.cas(),
356
+ upsert_result.mutation_token().value_or(couchbase::mutation_token{}));
357
+ state.add(upsert_result);
358
+ }
359
+
360
+ auto [ctx, result] =
361
+ cluster
362
+ .search_query("travel-sample-index", couchbase::query_string_query("bree"), couchbase::search_options{}.consistent_with(state))
363
+ .get();
364
+
365
+ if (ctx.ec()) {
366
+ fmt::print("unable to perform search query: {}, ({}, {})\n", ctx.ec().message(), ctx.status(), ctx.error());
367
+ return 1;
368
+ }
369
+ fmt::print("{} hits, total: {}\n", result.rows().size(), result.meta_data().metrics().total_rows());
370
+ for (const auto& row : result.rows()) {
371
+ fmt::print("id: {}, score: {}\n", row.id(), row.score());
372
+ }
373
+ }
374
+
375
+ {
376
+ fmt::print("--- complex query\n");
377
+ auto [ctx, result] = cluster
378
+ .search_query("travel-sample-index",
379
+ couchbase::boolean_query()
380
+ .must(couchbase::match_query("honeymoon").field("reviews.content"),
381
+ couchbase::numeric_range_query().field("reviews.ratings.Overall").min(4))
382
+ .must_not(couchbase::match_query("San Francisco").field("city")),
383
+ couchbase::search_options{}.collections({ "hotel" }).highlight())
384
+ .get();
385
+ if (ctx.ec()) {
386
+ fmt::print("unable to perform search query: {}, ({}, {})\n", ctx.ec().message(), ctx.status(), ctx.error());
387
+ return 1;
388
+ }
389
+ fmt::print("{} hits, total: {}\n", result.rows().size(), result.meta_data().metrics().total_rows());
390
+ for (const auto& row : result.rows()) {
391
+ fmt::print("id: {}, score: {}\n", row.id(), row.score());
392
+ }
393
+ }
394
+
395
+ {
396
+ fmt::print("--- simple query with facets\n");
397
+ auto [ctx, result] =
398
+ cluster
399
+ .search_query("travel-sample-index",
400
+ couchbase::query_string_query("honeymoon"),
401
+ couchbase::search_options{}.collections({ "hotel" }).facet("by_country", couchbase::term_facet("country", 3)))
402
+ .get();
403
+ if (ctx.ec()) {
404
+ fmt::print("unable to perform search query: {}, ({}, {})\n", ctx.ec().message(), ctx.status(), ctx.error());
405
+ return 1;
406
+ }
407
+ fmt::print("{} hits, total: {}\n", result.rows().size(), result.meta_data().metrics().total_rows());
408
+ for (const auto& [name, facet] : result.facets()) {
409
+ fmt::print("{} facet: total={}, missing={}\n", name, facet->total(), facet->missing());
410
+ if (name == "by_country") {
411
+ auto term_facet = std::static_pointer_cast<couchbase::term_facet_result>(facet);
412
+ for (const auto& group : term_facet->terms()) {
413
+ fmt::print("* {}: {}\n", group.name(), group.count());
414
+ }
415
+ }
416
+ }
417
+ }
418
+
419
+ // close cluster connection
420
+ cluster.close();
421
+ guard.reset();
422
+
423
+ io_thread.join();
424
+ return 0;
425
+ }
426
+
427
+ /*
428
+
429
+ $ ./example_search couchbase://127.0.0.1 Administrator password
430
+ saved document "my-document", cas=17486a1722b20000
431
+ retrieved document "my-document", name="mike"
432
+ row: {"airline":{"callsign":"MILE-AIR","country":"United States","iata":"Q5","icao":"MLA","id":10,"name":"40-Mile Air","type":"airline"}}
433
+
434
+ */
435
+ //! [example-search]
436
+ } // namespace example_search
437
+
438
+ TEST_CASE("example: search", "[integration]")
439
+ {
440
+ test::utils::integration_test_guard integration;
441
+ if (!integration.cluster_version().supports_collections()) {
442
+ return;
443
+ }
444
+
445
+ const auto env = test::utils::test_context::load_from_environment();
446
+ const char* argv[] = {
447
+ "example_search", // name of the "executable"
448
+ env.connection_string.c_str(),
449
+ env.username.c_str(),
450
+ env.password.c_str(),
451
+ };
452
+
453
+ REQUIRE(example_search::main(4, argv) == 0);
454
+ }