couchbase 3.0.2 → 3.0.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 (136) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/CMakeLists.txt +3 -0
  4. data/ext/build_version.hxx.in +1 -1
  5. data/ext/cmake/CompilerWarnings.cmake +1 -0
  6. data/ext/cmake/PreventInSourceBuilds.cmake +4 -1
  7. data/ext/couchbase/bucket.hxx +28 -2
  8. data/ext/couchbase/cluster.hxx +8 -2
  9. data/ext/couchbase/couchbase.cxx +955 -511
  10. data/ext/couchbase/error_context/analytics.hxx +46 -0
  11. data/ext/couchbase/error_context/http.hxx +44 -0
  12. data/ext/couchbase/error_context/key_value.hxx +47 -0
  13. data/ext/couchbase/error_context/query.hxx +46 -0
  14. data/ext/couchbase/error_context/search.hxx +47 -0
  15. data/ext/couchbase/error_context/view.hxx +47 -0
  16. data/ext/couchbase/io/dns_codec.hxx +1 -2
  17. data/ext/couchbase/io/http_command.hxx +16 -3
  18. data/ext/couchbase/io/http_context.hxx +1 -1
  19. data/ext/couchbase/io/http_session.hxx +12 -6
  20. data/ext/couchbase/io/http_session_manager.hxx +25 -24
  21. data/ext/couchbase/io/mcbp_session.hxx +8 -2
  22. data/ext/couchbase/io/retry_context.hxx +1 -1
  23. data/ext/couchbase/operations/analytics_dataset_create.hxx +19 -12
  24. data/ext/couchbase/operations/analytics_dataset_drop.hxx +18 -10
  25. data/ext/couchbase/operations/analytics_dataset_get_all.hxx +16 -10
  26. data/ext/couchbase/operations/analytics_dataverse_create.hxx +18 -11
  27. data/ext/couchbase/operations/analytics_dataverse_drop.hxx +17 -11
  28. data/ext/couchbase/operations/analytics_get_pending_mutations.hxx +17 -10
  29. data/ext/couchbase/operations/analytics_index_create.hxx +17 -11
  30. data/ext/couchbase/operations/analytics_index_drop.hxx +16 -10
  31. data/ext/couchbase/operations/analytics_index_get_all.hxx +14 -10
  32. data/ext/couchbase/operations/analytics_link_connect.hxx +15 -9
  33. data/ext/couchbase/operations/analytics_link_disconnect.hxx +16 -10
  34. data/ext/couchbase/operations/bucket_create.hxx +33 -10
  35. data/ext/couchbase/operations/bucket_drop.hxx +9 -8
  36. data/ext/couchbase/operations/bucket_flush.hxx +8 -8
  37. data/ext/couchbase/operations/bucket_get.hxx +15 -10
  38. data/ext/couchbase/operations/bucket_get_all.hxx +14 -7
  39. data/ext/couchbase/operations/bucket_settings.hxx +16 -0
  40. data/ext/couchbase/operations/bucket_update.hxx +32 -10
  41. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +6 -6
  42. data/ext/couchbase/operations/collection_create.hxx +19 -13
  43. data/ext/couchbase/operations/collection_drop.hxx +18 -12
  44. data/ext/couchbase/operations/collections_manifest_get.hxx +5 -10
  45. data/ext/couchbase/operations/document_analytics.hxx +39 -17
  46. data/ext/couchbase/operations/document_append.hxx +5 -10
  47. data/ext/couchbase/operations/document_decrement.hxx +5 -10
  48. data/ext/couchbase/operations/document_exists.hxx +4 -6
  49. data/ext/couchbase/operations/document_get.hxx +6 -10
  50. data/ext/couchbase/operations/document_get_and_lock.hxx +4 -9
  51. data/ext/couchbase/operations/document_get_and_touch.hxx +4 -9
  52. data/ext/couchbase/operations/document_get_projected.hxx +21 -14
  53. data/ext/couchbase/operations/document_increment.hxx +5 -10
  54. data/ext/couchbase/operations/document_insert.hxx +5 -10
  55. data/ext/couchbase/operations/document_lookup_in.hxx +4 -9
  56. data/ext/couchbase/operations/document_mutate_in.hxx +7 -12
  57. data/ext/couchbase/operations/document_prepend.hxx +5 -10
  58. data/ext/couchbase/operations/document_query.hxx +45 -28
  59. data/ext/couchbase/operations/document_remove.hxx +5 -10
  60. data/ext/couchbase/operations/document_replace.hxx +5 -10
  61. data/ext/couchbase/operations/document_search.hxx +37 -16
  62. data/ext/couchbase/operations/document_touch.hxx +4 -9
  63. data/ext/couchbase/operations/document_unlock.hxx +4 -9
  64. data/ext/couchbase/operations/document_upsert.hxx +5 -10
  65. data/ext/couchbase/operations/document_view.hxx +29 -13
  66. data/ext/couchbase/operations/group_drop.hxx +7 -7
  67. data/ext/couchbase/operations/group_get.hxx +14 -10
  68. data/ext/couchbase/operations/group_get_all.hxx +14 -8
  69. data/ext/couchbase/operations/group_upsert.hxx +15 -9
  70. data/ext/couchbase/operations/http_noop.hxx +5 -5
  71. data/ext/couchbase/operations/mcbp_noop.hxx +3 -9
  72. data/ext/couchbase/operations/query_index_build_deferred.hxx +15 -9
  73. data/ext/couchbase/operations/query_index_create.hxx +16 -10
  74. data/ext/couchbase/operations/query_index_drop.hxx +16 -10
  75. data/ext/couchbase/operations/query_index_get_all.hxx +13 -7
  76. data/ext/couchbase/operations/role_get_all.hxx +14 -8
  77. data/ext/couchbase/operations/scope_create.hxx +19 -13
  78. data/ext/couchbase/operations/scope_drop.hxx +17 -11
  79. data/ext/couchbase/operations/scope_get_all.hxx +15 -10
  80. data/ext/couchbase/operations/search_get_stats.hxx +5 -5
  81. data/ext/couchbase/operations/search_index_analyze_document.hxx +25 -13
  82. data/ext/couchbase/operations/search_index_control_ingest.hxx +23 -11
  83. data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +23 -11
  84. data/ext/couchbase/operations/search_index_control_query.hxx +23 -11
  85. data/ext/couchbase/operations/search_index_drop.hxx +22 -10
  86. data/ext/couchbase/operations/search_index_get.hxx +22 -10
  87. data/ext/couchbase/operations/search_index_get_all.hxx +13 -7
  88. data/ext/couchbase/operations/search_index_get_documents_count.hxx +24 -13
  89. data/ext/couchbase/operations/search_index_get_stats.hxx +16 -10
  90. data/ext/couchbase/operations/search_index_upsert.hxx +23 -11
  91. data/ext/couchbase/operations/user_drop.hxx +8 -8
  92. data/ext/couchbase/operations/user_get.hxx +14 -10
  93. data/ext/couchbase/operations/user_get_all.hxx +14 -8
  94. data/ext/couchbase/operations/user_upsert.hxx +15 -9
  95. data/ext/couchbase/operations/view_index_drop.hxx +7 -7
  96. data/ext/couchbase/operations/view_index_get.hxx +15 -9
  97. data/ext/couchbase/operations/view_index_get_all.hxx +15 -9
  98. data/ext/couchbase/operations/view_index_upsert.hxx +8 -8
  99. data/ext/couchbase/origin.hxx +1 -0
  100. data/ext/couchbase/platform/terminate_handler.cc +12 -8
  101. data/ext/couchbase/protocol/client_request.hxx +2 -1
  102. data/ext/couchbase/protocol/client_response.hxx +18 -15
  103. data/ext/couchbase/protocol/cmd_exists.hxx +1 -0
  104. data/ext/couchbase/protocol/cmd_get.hxx +1 -1
  105. data/ext/couchbase/protocol/cmd_mutate_in.hxx +3 -4
  106. data/ext/couchbase/protocol/enhanced_error_info.hxx +28 -0
  107. data/ext/couchbase/utils/connection_string.hxx +1 -1
  108. data/ext/couchbase/version.hxx +1 -1
  109. data/ext/extconf.rb +1 -1
  110. data/ext/test/test_native_binary_operations.cxx +18 -18
  111. data/ext/test/test_native_diagnostics.cxx +2 -2
  112. data/ext/test/test_native_trivial_crud.cxx +2 -2
  113. data/ext/third_party/json/include/tao/json/external/pegtl/internal/file_reader.hpp +1 -5
  114. data/lib/active_support/cache/couchbase_store.rb +362 -0
  115. data/lib/couchbase.rb +2 -0
  116. data/lib/couchbase/authenticator.rb +26 -0
  117. data/lib/couchbase/binary_collection.rb +1 -0
  118. data/lib/couchbase/bucket.rb +1 -0
  119. data/lib/couchbase/cluster.rb +51 -27
  120. data/lib/couchbase/collection.rb +19 -4
  121. data/lib/couchbase/collection_options.rb +10 -0
  122. data/lib/couchbase/configuration.rb +57 -0
  123. data/lib/couchbase/datastructures.rb +6 -0
  124. data/lib/couchbase/errors.rb +111 -3
  125. data/lib/couchbase/management.rb +27 -0
  126. data/lib/couchbase/management/bucket_manager.rb +9 -2
  127. data/lib/couchbase/management/collection_manager.rb +1 -1
  128. data/lib/couchbase/management/user_manager.rb +18 -2
  129. data/lib/couchbase/options.rb +33 -23
  130. data/lib/couchbase/railtie.rb +45 -0
  131. data/lib/couchbase/scope.rb +44 -3
  132. data/lib/couchbase/utils.rb +21 -0
  133. data/lib/couchbase/utils/time.rb +52 -0
  134. data/lib/couchbase/version.rb +1 -1
  135. data/lib/rails/generators/couchbase/config/config_generator.rb +27 -0
  136. metadata +19 -5
@@ -25,9 +25,7 @@ namespace couchbase::operations
25
25
  {
26
26
 
27
27
  struct append_response {
28
- document_id id;
29
- std::uint32_t opaque;
30
- std::error_code ec{};
28
+ error_context::key_value ctx;
31
29
  std::uint64_t cas{};
32
30
  mutation_token token{};
33
31
  };
@@ -59,17 +57,14 @@ struct append_request {
59
57
  };
60
58
 
61
59
  append_response
62
- make_response(std::error_code ec, append_request& request, append_request::encoded_response_type&& encoded)
60
+ make_response(error_context::key_value&& ctx, append_request& request, append_request::encoded_response_type&& encoded)
63
61
  {
64
- append_response response{ request.id, encoded.opaque(), ec };
65
- if (ec && response.opaque == 0) {
66
- response.opaque = request.opaque;
67
- }
68
- if (!ec) {
62
+ append_response response{ ctx };
63
+ if (!response.ctx.ec) {
69
64
  response.cas = encoded.cas();
70
65
  response.token = encoded.body().token();
71
66
  response.token.partition_id = request.partition;
72
- response.token.bucket_name = response.id.bucket;
67
+ response.token.bucket_name = response.ctx.id.bucket;
73
68
  }
74
69
  return response;
75
70
  }
@@ -25,9 +25,7 @@ namespace couchbase::operations
25
25
  {
26
26
 
27
27
  struct decrement_response {
28
- document_id id;
29
- std::uint32_t opaque;
30
- std::error_code ec{};
28
+ error_context::key_value ctx;
31
29
  std::uint64_t content{};
32
30
  std::uint64_t cas{};
33
31
  mutation_token token{};
@@ -69,18 +67,15 @@ struct decrement_request {
69
67
  };
70
68
 
71
69
  decrement_response
72
- make_response(std::error_code ec, decrement_request& request, decrement_request::encoded_response_type&& encoded)
70
+ make_response(error_context::key_value&& ctx, decrement_request& request, decrement_request::encoded_response_type&& encoded)
73
71
  {
74
- decrement_response response{ request.id, encoded.opaque(), ec };
75
- if (ec && response.opaque == 0) {
76
- response.opaque = request.opaque;
77
- }
78
- if (!ec) {
72
+ decrement_response response{ ctx };
73
+ if (!ctx.ec) {
79
74
  response.cas = encoded.cas();
80
75
  response.content = encoded.body().content();
81
76
  response.token = encoded.body().token();
82
77
  response.token.partition_id = request.partition;
83
- response.token.bucket_name = response.id.bucket;
78
+ response.token.bucket_name = response.ctx.id.bucket;
84
79
  }
85
80
  return response;
86
81
  }
@@ -27,9 +27,7 @@ namespace couchbase::operations
27
27
  struct exists_response {
28
28
  enum class observe_status { invalid, found, not_found, persisted, logically_deleted };
29
29
 
30
- document_id id;
31
- std::uint32_t opaque;
32
- std::error_code ec{};
30
+ error_context::key_value ctx;
33
31
  std::uint16_t partition_id{};
34
32
  std::uint64_t cas{};
35
33
  observe_status status{ observe_status::invalid };
@@ -54,10 +52,10 @@ struct exists_request {
54
52
  };
55
53
 
56
54
  exists_response
57
- make_response(std::error_code ec, exists_request& request, exists_request::encoded_response_type&& encoded)
55
+ make_response(error_context::key_value&& ctx, exists_request& request, exists_request::encoded_response_type&& encoded)
58
56
  {
59
- exists_response response{ request.id, encoded.opaque(), ec, request.partition };
60
- if (!ec) {
57
+ exists_response response{ ctx, request.partition };
58
+ if (!ctx.ec) {
61
59
  response.cas = encoded.body().cas();
62
60
  response.partition_id = encoded.body().partition_id();
63
61
  switch (encoded.body().status()) {
@@ -18,16 +18,15 @@
18
18
  #pragma once
19
19
 
20
20
  #include <document_id.hxx>
21
- #include <protocol/cmd_get.hxx>
21
+ #include <error_context/key_value.hxx>
22
22
  #include <io/retry_context.hxx>
23
+ #include <protocol/cmd_get.hxx>
23
24
 
24
25
  namespace couchbase::operations
25
26
  {
26
27
 
27
28
  struct get_response {
28
- document_id id;
29
- std::uint32_t opaque;
30
- std::error_code ec{};
29
+ error_context::key_value ctx;
31
30
  std::string value{};
32
31
  std::uint64_t cas{};
33
32
  std::uint32_t flags{};
@@ -53,13 +52,10 @@ struct get_request {
53
52
  };
54
53
 
55
54
  get_response
56
- make_response(std::error_code ec, get_request& request, get_request::encoded_response_type&& encoded)
55
+ make_response(error_context::key_value&& ctx, get_request&, get_request::encoded_response_type&& encoded)
57
56
  {
58
- get_response response{ request.id, encoded.opaque(), ec };
59
- if (ec && response.opaque == 0) {
60
- response.opaque = request.opaque;
61
- }
62
- if (!ec) {
57
+ get_response response{ ctx };
58
+ if (!response.ctx.ec) {
63
59
  response.value = std::move(encoded.body().value());
64
60
  response.cas = encoded.cas();
65
61
  response.flags = encoded.body().flags();
@@ -25,9 +25,7 @@ namespace couchbase::operations
25
25
  {
26
26
 
27
27
  struct get_and_lock_response {
28
- document_id id;
29
- std::uint32_t opaque;
30
- std::error_code ec{};
28
+ error_context::key_value ctx;
31
29
  std::string value{};
32
30
  std::uint64_t cas{};
33
31
  std::uint32_t flags{};
@@ -55,13 +53,10 @@ struct get_and_lock_request {
55
53
  };
56
54
 
57
55
  get_and_lock_response
58
- make_response(std::error_code ec, get_and_lock_request& request, get_and_lock_request::encoded_response_type&& encoded)
56
+ make_response(error_context::key_value&& ctx, get_and_lock_request&, get_and_lock_request::encoded_response_type&& encoded)
59
57
  {
60
- get_and_lock_response response{ request.id, encoded.opaque(), ec };
61
- if (ec && response.opaque == 0) {
62
- response.opaque = request.opaque;
63
- }
64
- if (!ec) {
58
+ get_and_lock_response response{ ctx };
59
+ if (!response.ctx.ec) {
65
60
  response.value = std::move(encoded.body().value());
66
61
  response.cas = encoded.cas();
67
62
  response.flags = encoded.body().flags();
@@ -25,9 +25,7 @@ namespace couchbase::operations
25
25
  {
26
26
 
27
27
  struct get_and_touch_response {
28
- document_id id;
29
- std::uint32_t opaque;
30
- std::error_code ec{};
28
+ error_context::key_value ctx;
31
29
  std::string value{};
32
30
  std::uint64_t cas{};
33
31
  std::uint32_t flags{};
@@ -55,13 +53,10 @@ struct get_and_touch_request {
55
53
  };
56
54
 
57
55
  get_and_touch_response
58
- make_response(std::error_code ec, get_and_touch_request& request, get_and_touch_request::encoded_response_type&& encoded)
56
+ make_response(error_context::key_value&& ctx, get_and_touch_request&, get_and_touch_request::encoded_response_type&& encoded)
59
57
  {
60
- get_and_touch_response response{ request.id, encoded.opaque(), ec };
61
- if (ec && response.opaque == 0) {
62
- response.opaque = request.opaque;
63
- }
64
- if (!ec) {
58
+ get_and_touch_response response{ ctx };
59
+ if (!response.ctx.ec) {
65
60
  response.value = std::move(encoded.body().value());
66
61
  response.cas = encoded.cas();
67
62
  response.flags = encoded.body().flags();
@@ -1,6 +1,6 @@
1
1
  /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright 2020 Couchbase, Inc.
3
+ * Copyright 2020-2021 Couchbase, Inc.
4
4
  *
5
5
  * Licensed under the Apache License, Version 2.0 (the "License");
6
6
  * you may not use this file except in compliance with the License.
@@ -25,9 +25,7 @@ namespace couchbase::operations
25
25
  {
26
26
 
27
27
  struct get_projected_response {
28
- document_id id;
29
- std::uint32_t opaque;
30
- std::error_code ec{};
28
+ error_context::key_value ctx;
31
29
  std::string value{};
32
30
  std::uint64_t cas{};
33
31
  std::uint32_t flags{};
@@ -198,13 +196,10 @@ subdoc_apply_projection(tao::json::value& root, const std::string& path, tao::js
198
196
  } // namespace priv
199
197
 
200
198
  get_projected_response
201
- make_response(std::error_code ec, get_projected_request& request, get_projected_request::encoded_response_type&& encoded)
199
+ make_response(error_context::key_value&& ctx, get_projected_request& request, get_projected_request::encoded_response_type&& encoded)
202
200
  {
203
- get_projected_response response{ request.id, encoded.opaque(), ec };
204
- if (ec && response.opaque == 0) {
205
- response.opaque = request.opaque;
206
- }
207
- if (!ec) {
201
+ get_projected_response response{ ctx };
202
+ if (!response.ctx.ec) {
208
203
  response.cas = encoded.cas();
209
204
  if (request.with_expiry && !encoded.body().fields()[0].value.empty()) {
210
205
  response.expiry = gsl::narrow_cast<std::uint32_t>(std::stoul(encoded.body().fields()[0].value));
@@ -215,14 +210,20 @@ make_response(std::error_code ec, get_projected_request& request, get_projected_
215
210
  // special case when user only wanted full+expiration
216
211
  response.value = encoded.body().fields()[1].value;
217
212
  } else {
218
- tao::json::value full_doc = tao::json::from_string(encoded.body().fields()[request.with_expiry ? 1 : 0].value);
213
+ tao::json::value full_doc{};
214
+ try {
215
+ full_doc = tao::json::from_string(encoded.body().fields()[request.with_expiry ? 1 : 0].value);
216
+ } catch (tao::json::pegtl::parse_error& e) {
217
+ response.ctx.ec = std::make_error_code(error::common_errc::parsing_failure);
218
+ return response;
219
+ }
219
220
  tao::json::value new_doc;
220
221
  for (const auto& projection : request.projections) {
221
222
  auto value_to_apply = priv::subdoc_lookup(full_doc, projection);
222
223
  if (value_to_apply) {
223
224
  priv::subdoc_apply_projection(new_doc, projection, *value_to_apply, request.preserve_array_indexes);
224
225
  } else {
225
- response.ec = std::make_error_code(error::key_value_errc::path_not_found);
226
+ response.ctx.ec = std::make_error_code(error::key_value_errc::path_not_found);
226
227
  return response;
227
228
  }
228
229
  }
@@ -234,10 +235,16 @@ make_response(std::error_code ec, get_projected_request& request, get_projected_
234
235
  for (const auto& projection : request.projections) {
235
236
  auto& field = encoded.body().fields()[offset++];
236
237
  if (field.status == protocol::status::success && !field.value.empty()) {
237
- auto value_to_apply = tao::json::from_string(field.value);
238
+ tao::json::value value_to_apply{};
239
+ try {
240
+ value_to_apply = tao::json::from_string(field.value);
241
+ } catch (tao::json::pegtl::parse_error& e) {
242
+ response.ctx.ec = std::make_error_code(error::common_errc::parsing_failure);
243
+ return response;
244
+ }
238
245
  priv::subdoc_apply_projection(new_doc, projection, value_to_apply, request.preserve_array_indexes);
239
246
  } else {
240
- response.ec = std::make_error_code(error::key_value_errc::path_not_found);
247
+ response.ctx.ec = std::make_error_code(error::key_value_errc::path_not_found);
241
248
  return response;
242
249
  }
243
250
  }
@@ -27,9 +27,7 @@ namespace couchbase::operations
27
27
  {
28
28
 
29
29
  struct increment_response {
30
- document_id id;
31
- std::uint32_t opaque;
32
- std::error_code ec{};
30
+ error_context::key_value ctx;
33
31
  std::uint64_t content{};
34
32
  std::uint64_t cas{};
35
33
  mutation_token token{};
@@ -71,18 +69,15 @@ struct increment_request {
71
69
  };
72
70
 
73
71
  increment_response
74
- make_response(std::error_code ec, increment_request& request, increment_request::encoded_response_type&& encoded)
72
+ make_response(error_context::key_value&& ctx, increment_request& request, increment_request::encoded_response_type&& encoded)
75
73
  {
76
- increment_response response{ request.id, encoded.opaque(), ec };
77
- if (ec && response.opaque == 0) {
78
- response.opaque = request.opaque;
79
- }
80
- if (!ec) {
74
+ increment_response response{ ctx };
75
+ if (!response.ctx.ec) {
81
76
  response.cas = encoded.cas();
82
77
  response.content = encoded.body().content();
83
78
  response.token = encoded.body().token();
84
79
  response.token.partition_id = request.partition;
85
- response.token.bucket_name = response.id.bucket;
80
+ response.token.bucket_name = response.ctx.id.bucket;
86
81
  }
87
82
  return response;
88
83
  }
@@ -26,9 +26,7 @@ namespace couchbase::operations
26
26
  {
27
27
 
28
28
  struct insert_response {
29
- document_id id;
30
- std::uint32_t opaque;
31
- std::error_code ec{};
29
+ error_context::key_value ctx;
32
30
  std::uint64_t cas{};
33
31
  mutation_token token{};
34
32
  };
@@ -64,17 +62,14 @@ struct insert_request {
64
62
  };
65
63
 
66
64
  insert_response
67
- make_response(std::error_code ec, insert_request& request, insert_request::encoded_response_type&& encoded)
65
+ make_response(error_context::key_value&& ctx, insert_request& request, insert_request::encoded_response_type&& encoded)
68
66
  {
69
- insert_response response{ request.id, encoded.opaque(), ec };
70
- if (ec && response.opaque == 0) {
71
- response.opaque = request.opaque;
72
- }
73
- if (!ec) {
67
+ insert_response response{ ctx };
68
+ if (!response.ctx.ec) {
74
69
  response.cas = encoded.cas();
75
70
  response.token = encoded.body().token();
76
71
  response.token.partition_id = request.partition;
77
- response.token.bucket_name = response.id.bucket;
72
+ response.token.bucket_name = response.ctx.id.bucket;
78
73
  }
79
74
  return response;
80
75
  }
@@ -34,9 +34,7 @@ struct lookup_in_response {
34
34
  std::string value;
35
35
  std::size_t original_index;
36
36
  };
37
- document_id id;
38
- std::uint32_t opaque;
39
- std::error_code ec{};
37
+ error_context::key_value ctx;
40
38
  std::uint64_t cas{};
41
39
  std::vector<field> fields{};
42
40
  bool deleted{ false };
@@ -78,17 +76,14 @@ struct lookup_in_request {
78
76
  };
79
77
 
80
78
  lookup_in_response
81
- make_response(std::error_code ec, lookup_in_request& request, lookup_in_request::encoded_response_type&& encoded)
79
+ make_response(error_context::key_value&& ctx, lookup_in_request& request, lookup_in_request::encoded_response_type&& encoded)
82
80
  {
83
- lookup_in_response response{ request.id, encoded.opaque(), ec };
84
- if (ec && response.opaque == 0) {
85
- response.opaque = request.opaque;
86
- }
81
+ lookup_in_response response{ ctx };
87
82
  if (encoded.status() == protocol::status::subdoc_success_deleted ||
88
83
  encoded.status() == protocol::status::subdoc_multi_path_failure_deleted) {
89
84
  response.deleted = true;
90
85
  }
91
- if (!ec) {
86
+ if (!ctx.ec) {
92
87
  response.cas = encoded.cas();
93
88
  response.fields.resize(request.specs.entries.size());
94
89
  for (size_t i = 0; i < request.specs.entries.size(); ++i) {
@@ -43,9 +43,7 @@ struct mutate_in_response {
43
43
  std::string value;
44
44
  std::size_t original_index;
45
45
  };
46
- document_id id;
47
- std::uint32_t opaque;
48
- std::error_code ec{};
46
+ error_context::key_value ctx;
49
47
  std::uint64_t cas{};
50
48
  mutation_token token{};
51
49
  std::vector<field> fields{};
@@ -109,21 +107,18 @@ struct mutate_in_request {
109
107
  };
110
108
 
111
109
  mutate_in_response
112
- make_response(std::error_code ec, mutate_in_request& request, mutate_in_request::encoded_response_type&& encoded)
110
+ make_response(error_context::key_value&& ctx, mutate_in_request& request, mutate_in_request::encoded_response_type&& encoded)
113
111
  {
114
- mutate_in_response response{ request.id, encoded.opaque(), ec };
115
- if (ec && response.opaque == 0) {
116
- response.opaque = request.opaque;
117
- }
112
+ mutate_in_response response{ ctx };
118
113
  if (encoded.status() == protocol::status::subdoc_success_deleted ||
119
114
  encoded.status() == protocol::status::subdoc_multi_path_failure_deleted) {
120
115
  response.deleted = true;
121
116
  }
122
- if (!ec) {
117
+ if (!response.ctx.ec) {
123
118
  response.cas = encoded.cas();
124
119
  response.token = encoded.body().token();
125
120
  response.token.partition_id = request.partition;
126
- response.token.bucket_name = response.id.bucket;
121
+ response.token.bucket_name = response.ctx.id.bucket;
127
122
  response.fields.resize(request.specs.entries.size());
128
123
  for (size_t i = 0; i < request.specs.entries.size(); ++i) {
129
124
  auto& req_entry = request.specs.entries[i];
@@ -147,8 +142,8 @@ make_response(std::error_code ec, mutate_in_request& request, mutate_in_request:
147
142
  return lhs.original_index < rhs.original_index;
148
143
  });
149
144
  } else if (request.store_semantics == protocol::mutate_in_request_body::store_semantics_type::insert &&
150
- ec == std::make_error_code(error::common_errc::cas_mismatch)) {
151
- response.ec = std::make_error_code(error::key_value_errc::document_exists);
145
+ response.ctx.ec == std::make_error_code(error::common_errc::cas_mismatch)) {
146
+ response.ctx.ec = std::make_error_code(error::key_value_errc::document_exists);
152
147
  }
153
148
  return response;
154
149
  }
@@ -25,9 +25,7 @@ namespace couchbase::operations
25
25
  {
26
26
 
27
27
  struct prepend_response {
28
- document_id id;
29
- std::uint32_t opaque;
30
- std::error_code ec{};
28
+ error_context::key_value ctx;
31
29
  std::uint64_t cas{};
32
30
  mutation_token token{};
33
31
  };
@@ -59,17 +57,14 @@ struct prepend_request {
59
57
  };
60
58
 
61
59
  prepend_response
62
- make_response(std::error_code ec, prepend_request& request, prepend_request::encoded_response_type&& encoded)
60
+ make_response(error_context::key_value&& ctx, prepend_request& request, prepend_request::encoded_response_type&& encoded)
63
61
  {
64
- prepend_response response{ request.id, encoded.opaque(), ec };
65
- if (ec && response.opaque == 0) {
66
- response.opaque = request.opaque;
67
- }
68
- if (!ec) {
62
+ prepend_response response{ ctx };
63
+ if (!response.ctx.ec) {
69
64
  response.cas = encoded.cas();
70
65
  response.token = encoded.body().token();
71
66
  response.token.partition_id = request.partition;
72
- response.token.bucket_name = response.id.bucket;
67
+ response.token.bucket_name = response.ctx.id.bucket;
73
68
  }
74
69
  return response;
75
70
  }
@@ -1,6 +1,6 @@
1
1
  /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright 2020 Couchbase, Inc.
3
+ * Copyright 2020-2021 Couchbase, Inc.
4
4
  *
5
5
  * Licensed under the Apache License, Version 2.0 (the "License");
6
6
  * you may not use this file except in compliance with the License.
@@ -26,12 +26,13 @@
26
26
  #include <version.hxx>
27
27
 
28
28
  #include <errors.hxx>
29
+ #include <io/http_context.hxx>
30
+ #include <io/http_message.hxx>
29
31
  #include <mutation_token.hxx>
30
- #include <service_type.hxx>
31
32
  #include <platform/uuid.h>
33
+ #include <service_type.hxx>
32
34
  #include <timeout_defaults.hxx>
33
- #include <io/http_message.hxx>
34
- #include <io/http_context.hxx>
35
+ #include <error_context/query.hxx>
35
36
 
36
37
  namespace couchbase::operations
37
38
  {
@@ -48,8 +49,8 @@ struct query_response_payload {
48
49
  };
49
50
 
50
51
  struct query_problem {
51
- std::uint64_t code;
52
- std::string message;
52
+ std::uint64_t code{};
53
+ std::string message{};
53
54
  };
54
55
 
55
56
  struct query_meta_data {
@@ -149,8 +150,7 @@ struct traits<couchbase::operations::query_response_payload> {
149
150
  namespace couchbase::operations
150
151
  {
151
152
  struct query_response {
152
- std::string client_context_id;
153
- std::error_code ec;
153
+ error_context::query ctx;
154
154
  query_response_payload payload{};
155
155
  };
156
156
 
@@ -158,6 +158,7 @@ struct query_request {
158
158
  using response_type = query_response;
159
159
  using encoded_request_type = io::http_request;
160
160
  using encoded_response_type = io::http_response;
161
+ using error_context_type = error_context::query;
161
162
 
162
163
  enum class scan_consistency_type { not_bounded, request_plus };
163
164
 
@@ -196,6 +197,8 @@ struct query_request {
196
197
  std::optional<http_context> ctx_{};
197
198
  bool extract_encoded_plan_{ false };
198
199
 
200
+ std::string body_str{};
201
+
199
202
  [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, http_context& context)
200
203
  {
201
204
  ctx_.emplace(context);
@@ -298,7 +301,7 @@ struct query_request {
298
301
  body["query_context"] = scope_qualifier;
299
302
  } else if (scope_name) {
300
303
  if (bucket_name) {
301
- body["query_context"] = fmt::format("`{}`.{}", *bucket_name, *scope_name);
304
+ body["query_context"] = fmt::format("default:`{}`.`{}`", *bucket_name, *scope_name);
302
305
  }
303
306
  }
304
307
  for (auto& param : raw) {
@@ -309,7 +312,8 @@ struct query_request {
309
312
  encoded.headers["content-type"] = "application/json";
310
313
  encoded.method = "POST";
311
314
  encoded.path = "/query/service";
312
- encoded.body = tao::json::to_string(body);
315
+ body_str = tao::json::to_string(body);
316
+ encoded.body = body_str;
313
317
 
314
318
  tao::json::value stmt = body["statement"];
315
319
  tao::json::value prep = body["prepared"];
@@ -329,11 +333,18 @@ struct query_request {
329
333
  };
330
334
 
331
335
  query_response
332
- make_response(std::error_code ec, query_request& request, query_request::encoded_response_type&& encoded)
336
+ make_response(error_context::query&& ctx, query_request& request, query_request::encoded_response_type&& encoded)
333
337
  {
334
- query_response response{ request.client_context_id, ec };
335
- if (!ec) {
336
- response.payload = tao::json::from_string(encoded.body).as<query_response_payload>();
338
+ query_response response{ ctx };
339
+ response.ctx.statement = request.statement;
340
+ response.ctx.parameters = request.body_str;
341
+ if (!response.ctx.ec) {
342
+ try {
343
+ response.payload = tao::json::from_string(encoded.body).as<query_response_payload>();
344
+ } catch (tao::json::pegtl::parse_error& e) {
345
+ response.ctx.ec = std::make_error_code(error::common_errc::parsing_failure);
346
+ return response;
347
+ }
337
348
  Expects(response.payload.meta_data.client_context_id.empty() ||
338
349
  response.payload.meta_data.client_context_id == request.client_context_id);
339
350
  if (response.payload.meta_data.status == "success") {
@@ -342,17 +353,23 @@ make_response(std::error_code ec, query_request& request, query_request::encoded
342
353
  } else if (request.extract_encoded_plan_) {
343
354
  request.extract_encoded_plan_ = false;
344
355
  if (response.payload.rows.size() == 1) {
345
- auto row = tao::json::from_string(response.payload.rows[0]);
346
- auto plan = row.find("encoded_plan");
347
- auto name = row.find("name");
356
+ tao::json::value row{};
357
+ try {
358
+ row = tao::json::from_string(response.payload.rows[0]);
359
+ } catch (tao::json::pegtl::parse_error& e) {
360
+ response.ctx.ec = std::make_error_code(error::common_errc::parsing_failure);
361
+ return response;
362
+ }
363
+ auto* plan = row.find("encoded_plan");
364
+ auto* name = row.find("name");
348
365
  if (plan != nullptr && name != nullptr) {
349
366
  request.ctx_->cache.put(request.statement, name->get_string(), plan->get_string());
350
367
  throw couchbase::priv::retry_http_request{};
351
- } else {
352
- response.ec = std::make_error_code(error::query_errc::prepared_statement_failure);
353
368
  }
369
+ response.ctx.ec = std::make_error_code(error::query_errc::prepared_statement_failure);
370
+
354
371
  } else {
355
- response.ec = std::make_error_code(error::query_errc::prepared_statement_failure);
372
+ response.ctx.ec = std::make_error_code(error::query_errc::prepared_statement_failure);
356
373
  }
357
374
  }
358
375
  } else {
@@ -399,21 +416,21 @@ make_response(std::error_code ec, query_request& request, query_request::encoded
399
416
  }
400
417
  }
401
418
  if (syntax_error) {
402
- response.ec = std::make_error_code(error::common_errc::parsing_failure);
419
+ response.ctx.ec = std::make_error_code(error::common_errc::parsing_failure);
403
420
  } else if (invalid_argument) {
404
- response.ec = std::make_error_code(error::common_errc::invalid_argument);
421
+ response.ctx.ec = std::make_error_code(error::common_errc::invalid_argument);
405
422
  } else if (server_timeout) {
406
- response.ec = std::make_error_code(error::common_errc::unambiguous_timeout);
423
+ response.ctx.ec = std::make_error_code(error::common_errc::unambiguous_timeout);
407
424
  } else if (prepared_statement_failure) {
408
- response.ec = std::make_error_code(error::query_errc::prepared_statement_failure);
425
+ response.ctx.ec = std::make_error_code(error::query_errc::prepared_statement_failure);
409
426
  } else if (index_failure) {
410
- response.ec = std::make_error_code(error::query_errc::index_failure);
427
+ response.ctx.ec = std::make_error_code(error::query_errc::index_failure);
411
428
  } else if (planning_failure) {
412
- response.ec = std::make_error_code(error::query_errc::planning_failure);
429
+ response.ctx.ec = std::make_error_code(error::query_errc::planning_failure);
413
430
  } else if (index_not_found) {
414
- response.ec = std::make_error_code(error::common_errc::index_not_found);
431
+ response.ctx.ec = std::make_error_code(error::common_errc::index_not_found);
415
432
  } else {
416
- response.ec = std::make_error_code(error::common_errc::internal_server_failure);
433
+ response.ctx.ec = std::make_error_code(error::common_errc::internal_server_failure);
417
434
  }
418
435
  }
419
436
  }