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
@@ -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.
@@ -19,15 +19,14 @@
19
19
 
20
20
  #include <tao/json.hpp>
21
21
 
22
- #include <version.hxx>
22
+ #include <error_context/http.hxx>
23
23
  #include <operations/bucket_settings.hxx>
24
24
 
25
25
  namespace couchbase::operations
26
26
  {
27
27
 
28
28
  struct bucket_get_response {
29
- std::string client_context_id;
30
- std::error_code ec;
29
+ error_context::http ctx;
31
30
  bucket_settings bucket{};
32
31
  };
33
32
 
@@ -35,6 +34,7 @@ struct bucket_get_request {
35
34
  using response_type = bucket_get_response;
36
35
  using encoded_request_type = io::http_request;
37
36
  using encoded_response_type = io::http_response;
37
+ using error_context_type = error_context::http;
38
38
 
39
39
  static const inline service_type type = service_type::management;
40
40
 
@@ -51,19 +51,24 @@ struct bucket_get_request {
51
51
  };
52
52
 
53
53
  bucket_get_response
54
- make_response(std::error_code ec, bucket_get_request& request, bucket_get_request::encoded_response_type&& encoded)
54
+ make_response(error_context::http&& ctx, bucket_get_request&, bucket_get_request::encoded_response_type&& encoded)
55
55
  {
56
- bucket_get_response response{ request.client_context_id, ec };
57
- if (!ec) {
56
+ bucket_get_response response{ ctx };
57
+ if (!response.ctx.ec) {
58
58
  switch (encoded.status_code) {
59
59
  case 404:
60
- response.ec = std::make_error_code(error::common_errc::bucket_not_found);
60
+ response.ctx.ec = std::make_error_code(error::common_errc::bucket_not_found);
61
61
  break;
62
62
  case 200:
63
- response.bucket = tao::json::from_string(encoded.body).as<bucket_settings>();
63
+ try {
64
+ response.bucket = tao::json::from_string(encoded.body).as<bucket_settings>();
65
+ } catch (tao::json::pegtl::parse_error& e) {
66
+ response.ctx.ec = std::make_error_code(error::common_errc::parsing_failure);
67
+ return response;
68
+ }
64
69
  break;
65
70
  default:
66
- response.ec = std::make_error_code(error::common_errc::internal_server_failure);
71
+ response.ctx.ec = std::make_error_code(error::common_errc::internal_server_failure);
67
72
  break;
68
73
  }
69
74
  }
@@ -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.
@@ -21,13 +21,13 @@
21
21
 
22
22
  #include <version.hxx>
23
23
  #include <operations/bucket_settings.hxx>
24
+ #include <error_context/http.hxx>
24
25
 
25
26
  namespace couchbase::operations
26
27
  {
27
28
 
28
29
  struct bucket_get_all_response {
29
- std::string client_context_id;
30
- std::error_code ec;
30
+ error_context::http ctx;
31
31
  std::vector<bucket_settings> buckets{};
32
32
  };
33
33
 
@@ -35,6 +35,7 @@ struct bucket_get_all_request {
35
35
  using response_type = bucket_get_all_response;
36
36
  using encoded_request_type = io::http_request;
37
37
  using encoded_response_type = io::http_response;
38
+ using error_context_type = error_context::http;
38
39
 
39
40
  static const inline service_type type = service_type::management;
40
41
  std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
@@ -49,11 +50,17 @@ struct bucket_get_all_request {
49
50
  };
50
51
 
51
52
  bucket_get_all_response
52
- make_response(std::error_code ec, bucket_get_all_request& request, bucket_get_all_request::encoded_response_type&& encoded)
53
+ make_response(error_context::http&& ctx, bucket_get_all_request&, bucket_get_all_request::encoded_response_type&& encoded)
53
54
  {
54
- bucket_get_all_response response{ request.client_context_id, ec };
55
- if (!ec) {
56
- auto payload = tao::json::from_string(encoded.body);
55
+ bucket_get_all_response response{ ctx };
56
+ if (!response.ctx.ec) {
57
+ tao::json::value payload{};
58
+ try {
59
+ payload = tao::json::from_string(encoded.body);
60
+ } catch (tao::json::pegtl::parse_error& e) {
61
+ response.ctx.ec = std::make_error_code(error::common_errc::parsing_failure);
62
+ return response;
63
+ }
57
64
  const auto& entries = payload.get_array();
58
65
  response.buckets.reserve(entries.size());
59
66
  for (const auto& entry : entries) {
@@ -56,6 +56,7 @@ struct bucket_settings {
56
56
  std::uint64_t ram_quota_mb{ 100 };
57
57
  std::uint32_t max_expiry{ 0 };
58
58
  compression_mode compression_mode{ compression_mode::unknown };
59
+ std::optional<protocol::durability_level> minimum_durability_level{};
59
60
  std::uint32_t num_replicas{ 1 };
60
61
  bool replica_indexes{ false };
61
62
  bool flush_enabled{ false };
@@ -112,6 +113,21 @@ struct traits<couchbase::operations::bucket_settings> {
112
113
  result.eviction_policy = couchbase::operations::bucket_settings::eviction_policy::not_recently_used;
113
114
  }
114
115
  }
116
+ {
117
+ auto* min_level = v.find("durabilityMinLevel");
118
+ if (min_level != nullptr) {
119
+ auto& str = min_level->get_string();
120
+ if (str == "none") {
121
+ result.minimum_durability_level = couchbase::protocol::durability_level::none;
122
+ } else if (str == "majority") {
123
+ result.minimum_durability_level = couchbase::protocol::durability_level::majority;
124
+ } else if (str == "majorityAndPersistActive") {
125
+ result.minimum_durability_level = couchbase::protocol::durability_level::majority_and_persist_to_active;
126
+ } else if (str == "persistToMajority") {
127
+ result.minimum_durability_level = couchbase::protocol::durability_level::persist_to_majority;
128
+ }
129
+ }
130
+ }
115
131
  {
116
132
  auto& str = v.at("conflictResolutionType").get_string();
117
133
  if (str == "lww") {
@@ -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.
@@ -27,8 +27,7 @@ namespace couchbase::operations
27
27
  {
28
28
 
29
29
  struct bucket_update_response {
30
- std::string client_context_id;
31
- std::error_code ec;
30
+ error_context::http ctx;
32
31
  bucket_settings bucket{};
33
32
  std::string error_message{};
34
33
  };
@@ -37,6 +36,7 @@ struct bucket_update_request {
37
36
  using response_type = bucket_update_response;
38
37
  using encoded_request_type = io::http_request;
39
38
  using encoded_response_type = io::http_response;
39
+ using error_context_type = error_context::http;
40
40
 
41
41
  static const inline service_type type = service_type::management;
42
42
  std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
@@ -84,22 +84,44 @@ struct bucket_update_request {
84
84
  case bucket_settings::compression_mode::unknown:
85
85
  break;
86
86
  }
87
+ if (bucket.minimum_durability_level) {
88
+ switch (bucket.minimum_durability_level.value()) {
89
+ case protocol::durability_level::none:
90
+ encoded.body.append("&durabilityMinLevel=none");
91
+ break;
92
+ case protocol::durability_level::majority:
93
+ encoded.body.append("&durabilityMinLevel=majority");
94
+ break;
95
+ case protocol::durability_level::majority_and_persist_to_active:
96
+ encoded.body.append("&durabilityMinLevel=majorityAndPersistActive");
97
+ break;
98
+ case protocol::durability_level::persist_to_majority:
99
+ encoded.body.append("&durabilityMinLevel=persistToMajority");
100
+ break;
101
+ }
102
+ }
87
103
  return {};
88
104
  }
89
105
  };
90
106
 
91
107
  bucket_update_response
92
- make_response(std::error_code ec, bucket_update_request& request, bucket_update_request::encoded_response_type&& encoded)
108
+ make_response(error_context::http&& ctx, bucket_update_request& /* request */, bucket_update_request::encoded_response_type&& encoded)
93
109
  {
94
- bucket_update_response response{ request.client_context_id, ec };
95
- if (!ec) {
110
+ bucket_update_response response{ ctx };
111
+ if (!response.ctx.ec) {
96
112
  switch (encoded.status_code) {
97
113
  case 404:
98
- response.ec = std::make_error_code(error::common_errc::bucket_not_found);
114
+ response.ctx.ec = std::make_error_code(error::common_errc::bucket_not_found);
99
115
  break;
100
116
  case 400: {
101
- response.ec = std::make_error_code(error::common_errc::invalid_argument);
102
- auto payload = tao::json::from_string(encoded.body);
117
+ tao::json::value payload{};
118
+ try {
119
+ payload = tao::json::from_string(encoded.body);
120
+ } catch (tao::json::pegtl::parse_error& e) {
121
+ response.ctx.ec = std::make_error_code(error::common_errc::parsing_failure);
122
+ return response;
123
+ }
124
+ response.ctx.ec = std::make_error_code(error::common_errc::invalid_argument);
103
125
  auto* errors = payload.find("errors");
104
126
  if (errors != nullptr) {
105
127
  std::vector<std::string> error_list{};
@@ -115,7 +137,7 @@ make_response(std::error_code ec, bucket_update_request& request, bucket_update_
115
137
  case 202:
116
138
  break;
117
139
  default:
118
- response.ec = std::make_error_code(error::common_errc::internal_server_failure);
140
+ response.ctx.ec = std::make_error_code(error::common_errc::internal_server_failure);
119
141
  break;
120
142
  }
121
143
  }
@@ -26,14 +26,14 @@ namespace couchbase::operations
26
26
  {
27
27
 
28
28
  struct cluster_developer_preview_enable_response {
29
- std::string client_context_id;
30
- std::error_code ec;
29
+ error_context::http ctx;
31
30
  };
32
31
 
33
32
  struct cluster_developer_preview_enable_request {
34
33
  using response_type = cluster_developer_preview_enable_response;
35
34
  using encoded_request_type = io::http_request;
36
35
  using encoded_response_type = io::http_response;
36
+ using error_context_type = error_context::http;
37
37
 
38
38
  static const inline service_type type = service_type::management;
39
39
  std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
@@ -50,12 +50,12 @@ struct cluster_developer_preview_enable_request {
50
50
  };
51
51
 
52
52
  cluster_developer_preview_enable_response
53
- make_response(std::error_code ec, cluster_developer_preview_enable_request& request, scope_get_all_request::encoded_response_type&& encoded)
53
+ make_response(error_context::http&& ctx, cluster_developer_preview_enable_request&, scope_get_all_request::encoded_response_type&& encoded)
54
54
  {
55
- cluster_developer_preview_enable_response response{ request.client_context_id, ec };
56
- if (!ec) {
55
+ cluster_developer_preview_enable_response response{ ctx };
56
+ if (!response.ctx.ec) {
57
57
  if (encoded.status_code != 200) {
58
- response.ec = std::make_error_code(error::common_errc::internal_server_failure);
58
+ response.ctx.ec = std::make_error_code(error::common_errc::internal_server_failure);
59
59
  }
60
60
  }
61
61
  return response;
@@ -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.
@@ -27,8 +27,7 @@ namespace couchbase::operations
27
27
  {
28
28
 
29
29
  struct collection_create_response {
30
- std::string client_context_id;
31
- std::error_code ec;
30
+ error_context::http ctx;
32
31
  std::uint64_t uid{ 0 };
33
32
  };
34
33
 
@@ -36,6 +35,7 @@ struct collection_create_request {
36
35
  using response_type = collection_create_response;
37
36
  using encoded_request_type = io::http_request;
38
37
  using encoded_response_type = io::http_response;
38
+ using error_context_type = error_context::http;
39
39
 
40
40
  static const inline service_type type = service_type::management;
41
41
 
@@ -60,33 +60,39 @@ struct collection_create_request {
60
60
  };
61
61
 
62
62
  collection_create_response
63
- make_response(std::error_code ec, collection_create_request& request, collection_create_request::encoded_response_type&& encoded)
63
+ make_response(error_context::http&& ctx, collection_create_request&, collection_create_request::encoded_response_type&& encoded)
64
64
  {
65
- collection_create_response response{ request.client_context_id, ec };
66
- if (!ec) {
65
+ collection_create_response response{ ctx };
66
+ if (!response.ctx.ec) {
67
67
  switch (encoded.status_code) {
68
68
  case 400:
69
69
  if (encoded.body.find("Collection with this name already exists") != std::string::npos) {
70
- response.ec = std::make_error_code(error::management_errc::collection_exists);
70
+ response.ctx.ec = std::make_error_code(error::management_errc::collection_exists);
71
71
  } else if (encoded.body.find("Not allowed on this version of cluster") != std::string::npos) {
72
- response.ec = std::make_error_code(error::common_errc::feature_not_available);
72
+ response.ctx.ec = std::make_error_code(error::common_errc::feature_not_available);
73
73
  } else {
74
- response.ec = std::make_error_code(error::common_errc::invalid_argument);
74
+ response.ctx.ec = std::make_error_code(error::common_errc::invalid_argument);
75
75
  }
76
76
  break;
77
77
  case 404:
78
78
  if (encoded.body.find("Scope with this name is not found") != std::string::npos) {
79
- response.ec = std::make_error_code(error::common_errc::scope_not_found);
79
+ response.ctx.ec = std::make_error_code(error::common_errc::scope_not_found);
80
80
  } else {
81
- response.ec = std::make_error_code(error::common_errc::bucket_not_found);
81
+ response.ctx.ec = std::make_error_code(error::common_errc::bucket_not_found);
82
82
  }
83
83
  break;
84
84
  case 200: {
85
- tao::json::value payload = tao::json::from_string(encoded.body);
85
+ tao::json::value payload{};
86
+ try {
87
+ payload = tao::json::from_string(encoded.body);
88
+ } catch (tao::json::pegtl::parse_error& e) {
89
+ response.ctx.ec = std::make_error_code(error::common_errc::parsing_failure);
90
+ return response;
91
+ }
86
92
  response.uid = std::stoull(payload.at("uid").get_string(), 0, 16);
87
93
  } break;
88
94
  default:
89
- response.ec = std::make_error_code(error::common_errc::internal_server_failure);
95
+ response.ctx.ec = std::make_error_code(error::common_errc::internal_server_failure);
90
96
  break;
91
97
  }
92
98
  }
@@ -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.
@@ -27,8 +27,7 @@ namespace couchbase::operations
27
27
  {
28
28
 
29
29
  struct collection_drop_response {
30
- std::string client_context_id;
31
- std::error_code ec;
30
+ error_context::http ctx;
32
31
  std::uint64_t uid{ 0 };
33
32
  };
34
33
 
@@ -36,6 +35,7 @@ struct collection_drop_request {
36
35
  using response_type = collection_drop_response;
37
36
  using encoded_request_type = io::http_request;
38
37
  using encoded_response_type = io::http_response;
38
+ using error_context_type = error_context::http;
39
39
 
40
40
  static const inline service_type type = service_type::management;
41
41
 
@@ -54,29 +54,35 @@ struct collection_drop_request {
54
54
  };
55
55
 
56
56
  collection_drop_response
57
- make_response(std::error_code ec, collection_drop_request& request, collection_drop_request::encoded_response_type&& encoded)
57
+ make_response(error_context::http&& ctx, collection_drop_request&, collection_drop_request::encoded_response_type&& encoded)
58
58
  {
59
- collection_drop_response response{ request.client_context_id, ec };
60
- if (!ec) {
59
+ collection_drop_response response{ ctx };
60
+ if (!response.ctx.ec) {
61
61
  switch (encoded.status_code) {
62
62
  case 400:
63
- response.ec = std::make_error_code(error::common_errc::unsupported_operation);
63
+ response.ctx.ec = std::make_error_code(error::common_errc::unsupported_operation);
64
64
  break;
65
65
  case 404:
66
66
  if (encoded.body.find("Collection with this name is not found") != std::string::npos) {
67
- response.ec = std::make_error_code(error::common_errc::collection_not_found);
67
+ response.ctx.ec = std::make_error_code(error::common_errc::collection_not_found);
68
68
  } else if (encoded.body.find("Scope with this name is not found") != std::string::npos) {
69
- response.ec = std::make_error_code(error::common_errc::scope_not_found);
69
+ response.ctx.ec = std::make_error_code(error::common_errc::scope_not_found);
70
70
  } else {
71
- response.ec = std::make_error_code(error::common_errc::bucket_not_found);
71
+ response.ctx.ec = std::make_error_code(error::common_errc::bucket_not_found);
72
72
  }
73
73
  break;
74
74
  case 200: {
75
- tao::json::value payload = tao::json::from_string(encoded.body);
75
+ tao::json::value payload{};
76
+ try {
77
+ payload = tao::json::from_string(encoded.body);
78
+ } catch (tao::json::pegtl::parse_error& e) {
79
+ response.ctx.ec = std::make_error_code(error::common_errc::parsing_failure);
80
+ return response;
81
+ }
76
82
  response.uid = std::stoull(payload.at("uid").get_string(), 0, 16);
77
83
  } break;
78
84
  default:
79
- response.ec = std::make_error_code(error::common_errc::internal_server_failure);
85
+ response.ctx.ec = std::make_error_code(error::common_errc::internal_server_failure);
80
86
  break;
81
87
  }
82
88
  }
@@ -31,9 +31,7 @@ namespace couchbase::operations
31
31
  {
32
32
 
33
33
  struct collections_manifest_get_response {
34
- document_id id;
35
- std::uint32_t opaque;
36
- std::error_code ec{};
34
+ error_context::key_value ctx;
37
35
  collections_manifest manifest{};
38
36
  };
39
37
 
@@ -55,15 +53,12 @@ struct collections_manifest_get_request {
55
53
  };
56
54
 
57
55
  collections_manifest_get_response
58
- make_response(std::error_code ec,
59
- collections_manifest_get_request& request,
56
+ make_response(error_context::key_value&& ctx,
57
+ collections_manifest_get_request&,
60
58
  collections_manifest_get_request::encoded_response_type&& encoded)
61
59
  {
62
- collections_manifest_get_response response{ request.id, encoded.opaque(), ec };
63
- if (ec && response.opaque == 0) {
64
- response.opaque = request.opaque;
65
- }
66
- if (!ec) {
60
+ collections_manifest_get_response response{ ctx };
61
+ if (!response.ctx.ec) {
67
62
  response.manifest = encoded.body().manifest();
68
63
  }
69
64
  return response;
@@ -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.
@@ -31,6 +31,7 @@
31
31
  #include <platform/uuid.h>
32
32
  #include <timeout_defaults.hxx>
33
33
  #include <io/http_message.hxx>
34
+ #include <error_context/analytics.hxx>
34
35
 
35
36
  namespace couchbase::operations
36
37
  {
@@ -139,8 +140,7 @@ struct traits<couchbase::operations::analytics_response_payload> {
139
140
  namespace couchbase::operations
140
141
  {
141
142
  struct analytics_response {
142
- std::string client_context_id;
143
- std::error_code ec;
143
+ error_context::analytics ctx;
144
144
  analytics_response_payload payload{};
145
145
  };
146
146
 
@@ -148,6 +148,7 @@ struct analytics_request {
148
148
  using response_type = analytics_response;
149
149
  using encoded_request_type = io::http_request;
150
150
  using encoded_response_type = io::http_response;
151
+ using error_context_type = error_context::analytics;
151
152
 
152
153
  enum class scan_consistency_type { not_bounded, request_plus };
153
154
 
@@ -159,6 +160,9 @@ struct analytics_request {
159
160
 
160
161
  bool readonly{ false };
161
162
  bool priority{ false };
163
+ std::optional<std::string> bucket_name{};
164
+ std::optional<std::string> scope_name{};
165
+ std::optional<std::string> scope_qualifier{};
162
166
 
163
167
  std::optional<scan_consistency_type> scan_consistency{};
164
168
 
@@ -166,6 +170,8 @@ struct analytics_request {
166
170
  std::vector<tao::json::value> positional_parameters{};
167
171
  std::map<std::string, tao::json::value> named_parameters{};
168
172
 
173
+ std::string body_str{};
174
+
169
175
  [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, http_context& context)
170
176
  {
171
177
  tao::json::value body{ { "statement", statement },
@@ -196,6 +202,14 @@ struct analytics_request {
196
202
  break;
197
203
  }
198
204
  }
205
+ if (scope_qualifier) {
206
+ body["query_context"] = scope_qualifier;
207
+ } else if (scope_name) {
208
+ if (bucket_name) {
209
+ // for analytics bucket_name.scope_name is quoted as a single unit (unlike n1ql query)
210
+ body["query_context"] = fmt::format("default:`{}.{}`", *bucket_name, *scope_name);
211
+ }
212
+ }
199
213
  for (auto& param : raw) {
200
214
  body[param.first] = param.second;
201
215
  }
@@ -206,7 +220,8 @@ struct analytics_request {
206
220
  }
207
221
  encoded.method = "POST";
208
222
  encoded.path = "/query/service";
209
- encoded.body = tao::json::to_string(body);
223
+ body_str = tao::json::to_string(body);
224
+ encoded.body = body_str;
210
225
  if (context.options.show_queries) {
211
226
  spdlog::info("ANALYTICS: {}", tao::json::to_string(body["statement"]));
212
227
  } else {
@@ -217,11 +232,18 @@ struct analytics_request {
217
232
  };
218
233
 
219
234
  analytics_response
220
- make_response(std::error_code ec, analytics_request& request, analytics_request::encoded_response_type&& encoded)
235
+ make_response(error_context::analytics&& ctx, analytics_request& request, analytics_request::encoded_response_type&& encoded)
221
236
  {
222
- analytics_response response{ request.client_context_id, ec };
223
- if (!ec) {
224
- response.payload = tao::json::from_string(encoded.body).as<analytics_response_payload>();
237
+ analytics_response response{ ctx };
238
+ response.ctx.statement = request.statement;
239
+ response.ctx.parameters = request.body_str;
240
+ if (!response.ctx.ec) {
241
+ try {
242
+ response.payload = tao::json::from_string(encoded.body).as<analytics_response_payload>();
243
+ } catch (tao::json::pegtl::parse_error& e) {
244
+ response.ctx.ec = std::make_error_code(error::common_errc::parsing_failure);
245
+ return response;
246
+ }
225
247
  Expects(response.payload.meta_data.client_context_id == request.client_context_id);
226
248
  if (response.payload.meta_data.status != "success") {
227
249
  bool server_timeout = false;
@@ -268,23 +290,23 @@ make_response(std::error_code ec, analytics_request& request, analytics_request:
268
290
  }
269
291
  }
270
292
  if (compilation_failure) {
271
- response.ec = std::make_error_code(error::analytics_errc::compilation_failure);
293
+ response.ctx.ec = std::make_error_code(error::analytics_errc::compilation_failure);
272
294
  } else if (link_not_found) {
273
- response.ec = std::make_error_code(error::analytics_errc::link_not_found);
295
+ response.ctx.ec = std::make_error_code(error::analytics_errc::link_not_found);
274
296
  } else if (dataset_not_found) {
275
- response.ec = std::make_error_code(error::analytics_errc::dataset_not_found);
297
+ response.ctx.ec = std::make_error_code(error::analytics_errc::dataset_not_found);
276
298
  } else if (dataverse_not_found) {
277
- response.ec = std::make_error_code(error::analytics_errc::dataverse_not_found);
299
+ response.ctx.ec = std::make_error_code(error::analytics_errc::dataverse_not_found);
278
300
  } else if (server_timeout) {
279
- response.ec = std::make_error_code(error::common_errc::unambiguous_timeout);
301
+ response.ctx.ec = std::make_error_code(error::common_errc::unambiguous_timeout);
280
302
  } else if (dataset_exists) {
281
- response.ec = std::make_error_code(error::analytics_errc::dataset_exists);
303
+ response.ctx.ec = std::make_error_code(error::analytics_errc::dataset_exists);
282
304
  } else if (dataverse_exists) {
283
- response.ec = std::make_error_code(error::analytics_errc::dataverse_exists);
305
+ response.ctx.ec = std::make_error_code(error::analytics_errc::dataverse_exists);
284
306
  } else if (job_queue_is_full) {
285
- response.ec = std::make_error_code(error::analytics_errc::job_queue_full);
307
+ response.ctx.ec = std::make_error_code(error::analytics_errc::job_queue_full);
286
308
  } else {
287
- response.ec = std::make_error_code(error::common_errc::internal_server_failure);
309
+ response.ctx.ec = std::make_error_code(error::common_errc::internal_server_failure);
288
310
  }
289
311
  }
290
312
  }