couchbase 4.1.0 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. package/README.md +8 -0
  2. package/deps/couchbase-cxx-client/.github/workflows/linters.yml +2 -2
  3. package/deps/couchbase-cxx-client/.github/workflows/sanitizers.yml +18 -2
  4. package/deps/couchbase-cxx-client/.github/workflows/tests.yml +14 -34
  5. package/deps/couchbase-cxx-client/.github/workflows/windows.yml +13 -15
  6. package/deps/couchbase-cxx-client/CMakeLists.txt +6 -1
  7. package/deps/couchbase-cxx-client/bin/build-tests +3 -0
  8. package/deps/couchbase-cxx-client/bin/build-tests.rb +3 -0
  9. package/deps/couchbase-cxx-client/bin/init-cluster +1 -1
  10. package/deps/couchbase-cxx-client/bin/run-tests +1 -1
  11. package/deps/couchbase-cxx-client/cmake/StandardProjectSettings.cmake +1 -1
  12. package/deps/couchbase-cxx-client/couchbase/cluster.hxx +25 -6
  13. package/deps/couchbase-cxx-client/couchbase/io/mcbp_session.hxx +21 -7
  14. package/deps/couchbase-cxx-client/couchbase/meta/version.cxx +7 -0
  15. package/deps/couchbase-cxx-client/couchbase/operations/document_decrement.cxx +0 -3
  16. package/deps/couchbase-cxx-client/couchbase/operations/document_decrement.hxx +0 -1
  17. package/deps/couchbase-cxx-client/couchbase/operations/document_increment.cxx +0 -3
  18. package/deps/couchbase-cxx-client/couchbase/operations/document_increment.hxx +0 -1
  19. package/deps/couchbase-cxx-client/couchbase/operations/management/analytics_dataset_get_all.cxx +1 -1
  20. package/deps/couchbase-cxx-client/couchbase/operations/management/analytics_get_pending_mutations.cxx +1 -1
  21. package/deps/couchbase-cxx-client/couchbase/operations/management/analytics_get_pending_mutations.hxx +1 -1
  22. package/deps/couchbase-cxx-client/couchbase/operations/management/query_index_drop.cxx +4 -3
  23. package/deps/couchbase-cxx-client/couchbase/origin.hxx +10 -0
  24. package/deps/couchbase-cxx-client/couchbase/protocol/cmd_decrement.cxx +3 -8
  25. package/deps/couchbase-cxx-client/couchbase/protocol/cmd_decrement.hxx +0 -2
  26. package/deps/couchbase-cxx-client/couchbase/protocol/cmd_increment.cxx +0 -9
  27. package/deps/couchbase-cxx-client/couchbase/protocol/cmd_increment.hxx +0 -2
  28. package/deps/couchbase-cxx-client/couchbase/utils/json_streaming_lexer.cxx +6 -2
  29. package/deps/couchbase-cxx-client/test/test_integration_collections.cxx +4 -6
  30. package/deps/couchbase-cxx-client/test/test_integration_connect.cxx +4 -0
  31. package/deps/couchbase-cxx-client/test/test_integration_management.cxx +194 -138
  32. package/deps/couchbase-cxx-client/test/test_integration_query.cxx +26 -10
  33. package/deps/couchbase-cxx-client/test/test_unit_json_streaming_lexer.cxx +119 -0
  34. package/deps/couchbase-cxx-client/test/utils/integration_test_guard.cxx +1 -1
  35. package/deps/couchbase-cxx-client/test/utils/server_version.cxx +2 -1
  36. package/deps/couchbase-cxx-client/test/utils/server_version.hxx +22 -4
  37. package/deps/couchbase-cxx-client/test/utils/test_context.cxx +11 -1
  38. package/deps/couchbase-cxx-client/test/utils/test_context.hxx +1 -0
  39. package/deps/couchbase-transactions-cxx/CMakeLists.txt +2 -2
  40. package/deps/couchbase-transactions-cxx/deps/couchbase-cxx-client/couchbase/{management/design_document_fmt.hxx → design_document_namespace_fmt.hxx} +5 -5
  41. package/deps/couchbase-transactions-cxx/deps/couchbase-cxx-client/couchbase/operations/management/query_index_get_all.cxx +26 -16
  42. package/deps/couchbase-transactions-cxx/include/couchbase/transactions/durability_level.hxx +15 -0
  43. package/deps/couchbase-transactions-cxx/include/couchbase/transactions.hxx +2 -6
  44. package/deps/couchbase-transactions-cxx/src/transactions/attempt_context_impl.cxx +1 -1
  45. package/deps/couchbase-transactions-cxx/src/transactions/logging.cxx +20 -17
  46. package/deps/couchbase-transactions-cxx/tests/transactions/simple_t.cpp +22 -0
  47. package/deps/couchbase-transactions-cxx/tests/transactions/transactions_env.h +1 -1
  48. package/dist/binding.d.ts +0 -2
  49. package/dist/collection.js +0 -2
  50. package/dist/httpexecutor.d.ts +1 -0
  51. package/package.json +1 -1
  52. package/src/jstocbpp_autogen.hpp +3 -9
  53. package/deps/couchbase-cxx-client/.github/workflows/benchmarks.yml +0 -94
  54. package/deps/couchbase-transactions-cxx/deps/couchbase-cxx-client/.github/workflows/benchmarks.yml +0 -94
@@ -82,28 +82,22 @@ TEST_CASE("integration: query on a collection", "[integration]")
82
82
  };
83
83
  auto json = couchbase::utils::json::generate(value);
84
84
 
85
- uint64_t scope_uid;
86
- uint64_t collection_uid;
87
-
88
85
  {
89
86
  couchbase::operations::management::scope_create_request req{ integration.ctx.bucket, scope_name };
90
87
  auto resp = test::utils::execute(integration.cluster, req);
91
88
  REQUIRE_FALSE(resp.ctx.ec);
92
- scope_uid = resp.uid;
89
+ auto created = test::utils::wait_until_collection_manifest_propagated(integration.cluster, integration.ctx.bucket, resp.uid);
90
+ REQUIRE(created);
93
91
  }
94
92
 
95
93
  {
96
94
  couchbase::operations::management::collection_create_request req{ integration.ctx.bucket, scope_name, collection_name };
97
95
  auto resp = test::utils::execute(integration.cluster, req);
98
96
  REQUIRE_FALSE(resp.ctx.ec);
99
- collection_uid = resp.uid;
97
+ auto created = test::utils::wait_until_collection_manifest_propagated(integration.cluster, integration.ctx.bucket, resp.uid);
98
+ REQUIRE(created);
100
99
  }
101
100
 
102
- auto current_manifest_uid = std::max(collection_uid, scope_uid);
103
- auto created =
104
- test::utils::wait_until_collection_manifest_propagated(integration.cluster, integration.ctx.bucket, current_manifest_uid);
105
- REQUIRE(created);
106
-
107
101
  {
108
102
  couchbase::operations::management::query_index_create_request req{};
109
103
  req.bucket_name = integration.ctx.bucket;
@@ -405,3 +399,25 @@ TEST_CASE("integration: sticking query to the service node", "[integration]")
405
399
  REQUIRE(std::set(used_nodes.begin(), used_nodes.end()).size() == 1);
406
400
  }
407
401
  }
402
+
403
+ TEST_CASE("analytics create dataset")
404
+ {
405
+ test::utils::integration_test_guard integration;
406
+
407
+ if (!integration.cluster_version().supports_analytics() || !integration.has_analytics_service() ||
408
+ !integration.cluster_version().supports_collections()) {
409
+ return;
410
+ }
411
+ if (!integration.cluster_version().supports_gcccp()) {
412
+ test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
413
+ }
414
+ couchbase::operations::analytics_request req{ fmt::format("CREATE DATAVERSE `{}`.`test-scope` IF NOT EXISTS", integration.ctx.bucket) };
415
+ std::vector<std::string> rows{};
416
+ req.row_callback = [&rows](std::string&& row) {
417
+ rows.emplace_back(std::move(row));
418
+ return couchbase::utils::json::stream_control::next_row;
419
+ };
420
+
421
+ auto resp = test::utils::execute(integration.cluster, req);
422
+ REQUIRE_FALSE(resp.ctx.ec);
423
+ }
@@ -113,3 +113,122 @@ TEST_CASE("unit: json_streaming_lexer parse query result", "[unit]")
113
113
  REQUIRE(result.rows.size() == 3);
114
114
  REQUIRE(result.meta == chunks[0] + chunks[4]);
115
115
  }
116
+
117
+ TEST_CASE("unit: json_streaming_lexer parse query result in multiple chunks", "[unit]")
118
+ {
119
+ test::utils::init_logger();
120
+
121
+ const std::vector<std::string> chunks{
122
+ /* 0 */
123
+ R"({"requestID": "34a4e4b2-3f69-4bf8-a6e2-ae06798de3d9","clientContextID": "dfea5193-ead9-4ac2-5558-8fd5c4631959","signature": {"greeting":"string"},"results": [{"greeting":"ruby rules"}],"status": "success","profile": {"phaseTimes": {"authorize":"10.473µs","instantiate":"10.29µs","parse":"183.413µs","plan":"19.155µs","project":"5.712µs","run":"43.258µs","stream":"7.078µs"},"phaseOperators": {"authorize":1,"project":1,"stream":1},"requestTime": "2022-05-11T11:01:14.943Z","servicingHost": "10.112.220.101:8091","executionTimings": {"#operator":"Authorize","#stats":{"#phaseSwitches":4,"execTime":"1.372µs","servTime":"9.101µs"},"privileges":{"List":[]},"~child":{"#operator":"Sequence","#stats":{"#phaseSwitches":2,"execTime":"838ns"},"~children":[{"#operator":"DummyScan","#stats":{"#itemsOut":1,"#phaseSwitches":3,"execTime":"794ns","kernTime":"514ns"},"optimizer_estimates":{"cardinality":1,"cost":1.0842021724855044e-19,"fr_cost":1.0842021724855044e-19,"size":1}},{"#operator":"InitialProject","#stats":{"#itemsIn":1,"#itemsOut":1,"#phaseSwitches":8,"execTime":"110.717µs","kernTime":"4.786µs","state":"running"},"optimizer_estimates":{"cardinality":1,"cost":0.001,"fr_cost":0.001,"size":1},"result_terms":[{"as":"greeting","expr":"\"ruby rules\""}]},{"#operator":"Stream","#stats":{"#itemsIn":)",
124
+ /* 1 */
125
+ R"(1,"#itemsOut":1,"#phaseSwitches":2,"execTime":"7.078µs"},"optimizer_estimates":{"cardinality":1,"cost":0.001,"fr_cost":0.001,"size":1}}]},"~versions":["7.1.0-N1QL","7.1.0-2534-enterprise"]},"optimizerEstimates": {"cardinality":1,"cost":0.001}}})"
126
+ };
127
+
128
+ couchbase::utils::json::streaming_lexer lexer("/results/^", 4);
129
+ query_result result{};
130
+ lexer.on_row([&result](std::string&& row) {
131
+ result.rows.emplace_back(std::move(row));
132
+ return couchbase::utils::json::stream_control::next_row;
133
+ });
134
+ lexer.on_complete([&result](std::error_code ec, std::size_t number_of_rows, std::string&& meta) {
135
+ result.ec = ec;
136
+ result.number_of_rows = number_of_rows;
137
+ result.meta = std::move(meta);
138
+ });
139
+ for (const auto& chunk : chunks) {
140
+ lexer.feed(chunk);
141
+ }
142
+ REQUIRE_FALSE(result.ec);
143
+ REQUIRE(result.number_of_rows == 1);
144
+ REQUIRE(result.rows.size() == 1);
145
+
146
+ const auto* expected_meta =
147
+ R"({"requestID": "34a4e4b2-3f69-4bf8-a6e2-ae06798de3d9","clientContextID": "dfea5193-ead9-4ac2-5558-8fd5c4631959","signature": {"greeting":"string"},"results": [],"status": "success","profile": {"phaseTimes": {"authorize":"10.473µs","instantiate":"10.29µs","parse":"183.413µs","plan":"19.155µs","project":"5.712µs","run":"43.258µs","stream":"7.078µs"},"phaseOperators": {"authorize":1,"project":1,"stream":1},"requestTime": "2022-05-11T11:01:14.943Z","servicingHost": "10.112.220.101:8091","executionTimings": {"#operator":"Authorize","#stats":{"#phaseSwitches":4,"execTime":"1.372µs","servTime":"9.101µs"},"privileges":{"List":[]},"~child":{"#operator":"Sequence","#stats":{"#phaseSwitches":2,"execTime":"838ns"},"~children":[{"#operator":"DummyScan","#stats":{"#itemsOut":1,"#phaseSwitches":3,"execTime":"794ns","kernTime":"514ns"},"optimizer_estimates":{"cardinality":1,"cost":1.0842021724855044e-19,"fr_cost":1.0842021724855044e-19,"size":1}},{"#operator":"InitialProject","#stats":{"#itemsIn":1,"#itemsOut":1,"#phaseSwitches":8,"execTime":"110.717µs","kernTime":"4.786µs","state":"running"},"optimizer_estimates":{"cardinality":1,"cost":0.001,"fr_cost":0.001,"size":1},"result_terms":[{"as":"greeting","expr":"\"ruby rules\""}]},{"#operator":"Stream","#stats":{"#itemsIn":1,"#itemsOut":1,"#phaseSwitches":2,"execTime":"7.078µs"},"optimizer_estimates":{"cardinality":1,"cost":0.001,"fr_cost":0.001,"size":1}}]},"~versions":["7.1.0-N1QL","7.1.0-2534-enterprise"]},"optimizerEstimates": {"cardinality":1,"cost":0.001}}})";
148
+
149
+ REQUIRE(result.meta == expected_meta);
150
+ }
151
+
152
+ TEST_CASE("unit: json_streaming_lexer parse chunked metadata trailer", "[unit]")
153
+ {
154
+ test::utils::init_logger();
155
+
156
+ const std::vector<std::string> chunks{
157
+ /* 0 */
158
+ R"({"requestID": "2640a5b5-2e67-44e7-86ec-31cc388b7427","results": [42],)",
159
+ /* 1 */
160
+ R"("clientContextID":)",
161
+ /* 2 */
162
+ R"("730ecac3-e8d0-4d6e-4ed9-e2d4abd1d7b9",)",
163
+ /* 3 */
164
+ R"("status": "success"})",
165
+ };
166
+ couchbase::utils::json::streaming_lexer lexer("/results/^", 4);
167
+ query_result result{};
168
+ lexer.on_row([&result](std::string&& row) {
169
+ result.rows.emplace_back(std::move(row));
170
+ return couchbase::utils::json::stream_control::next_row;
171
+ });
172
+ lexer.on_complete([&result](std::error_code ec, std::size_t number_of_rows, std::string&& meta) {
173
+ result.ec = ec;
174
+ result.number_of_rows = number_of_rows;
175
+ result.meta = std::move(meta);
176
+ });
177
+ for (const auto& chunk : chunks) {
178
+ lexer.feed(chunk);
179
+ }
180
+ REQUIRE_FALSE(result.ec);
181
+ REQUIRE(result.number_of_rows == 1);
182
+ REQUIRE(result.rows.size() == 1);
183
+ const auto* expected_meta =
184
+ R"({"requestID": "2640a5b5-2e67-44e7-86ec-31cc388b7427","results": [],"clientContextID":"730ecac3-e8d0-4d6e-4ed9-e2d4abd1d7b9","status": "success"})";
185
+ REQUIRE(result.meta == expected_meta);
186
+ REQUIRE(result.rows[0] == R"(42)");
187
+ }
188
+
189
+ TEST_CASE("unit: json_streaming_lexer parse payload with missing results", "[unit]")
190
+ {
191
+ test::utils::init_logger();
192
+
193
+ std::string chunk = R"(
194
+ {
195
+
196
+ "requestID": "d07c0cde-cd80-4620-bb6b-d0641f272420",
197
+ "clientContextID": "a7bbe750-20a2-4e46-eb67-315e3733b2a8",
198
+ "signature": {
199
+ "*": "*"
200
+ },
201
+ "plans":{},
202
+ "status": "success",
203
+ "metrics": {
204
+ "elapsedTime": "6.56579ms",
205
+ "executionTime": "5.552905ms",
206
+ "resultCount": 0,
207
+ "resultSize": 0,
208
+ "processedObjects": 0
209
+ }
210
+ }
211
+ )";
212
+ couchbase::utils::json::streaming_lexer lexer("/results/^", 4);
213
+ query_result result{};
214
+ bool on_row_handler_executed = false;
215
+ lexer.on_row([&result, &on_row_handler_executed](std::string&& row) {
216
+ on_row_handler_executed = true;
217
+ result.rows.emplace_back(std::move(row));
218
+ return couchbase::utils::json::stream_control::next_row;
219
+ });
220
+ bool on_complete_handler_excecuted = false;
221
+ lexer.on_complete([&result, &on_complete_handler_excecuted](std::error_code ec, std::size_t number_of_rows, std::string&& meta) {
222
+ on_complete_handler_excecuted = true;
223
+ result.ec = ec;
224
+ result.number_of_rows = number_of_rows;
225
+ result.meta = std::move(meta);
226
+ });
227
+ lexer.feed(chunk);
228
+ REQUIRE_FALSE(on_row_handler_executed);
229
+ REQUIRE(on_complete_handler_excecuted);
230
+ REQUIRE_FALSE(result.ec);
231
+ REQUIRE(result.number_of_rows == 0);
232
+ REQUIRE(result.rows.empty());
233
+ REQUIRE(result.meta == chunk);
234
+ }
@@ -105,7 +105,7 @@ integration_test_guard::cluster_version()
105
105
  if (runtime_version.empty()) {
106
106
  return ctx.version;
107
107
  }
108
- auto parsed_version = server_version::parse(runtime_version);
108
+ auto parsed_version = server_version::parse(runtime_version, ctx.deployment);
109
109
  if (parsed_version.major == 0) {
110
110
  /* the build does not specify version properly */
111
111
  return ctx.version;
@@ -22,11 +22,12 @@
22
22
  namespace test::utils
23
23
  {
24
24
  server_version
25
- server_version::parse(const std::string& str)
25
+ server_version::parse(const std::string& str, const deployment_type deployment)
26
26
  {
27
27
  std::regex version_regex(R"((\d+).(\d+).(\d+)(-(\d+))?(-(.+))?)");
28
28
  std::smatch version_match{};
29
29
  server_version ver{};
30
+ ver.deployment = deployment;
30
31
  if (std::regex_match(str, version_match, version_regex) && version_match.ready()) {
31
32
  ver.major = std::stoul(version_match[1]);
32
33
  ver.minor = std::stoul(version_match[2]);
@@ -25,6 +25,8 @@ namespace test::utils
25
25
 
26
26
  enum class server_edition { unknown, enterprise, community };
27
27
 
28
+ enum class deployment_type { on_prem, capella, elixir };
29
+
28
30
  struct server_version {
29
31
  unsigned long major{ 0 };
30
32
  unsigned long minor{ 0 };
@@ -32,8 +34,9 @@ struct server_version {
32
34
  unsigned long build{ 0 };
33
35
  bool developer_preview{ false };
34
36
  server_edition edition{ server_edition::unknown };
37
+ deployment_type deployment{ deployment_type::on_prem };
35
38
 
36
- static server_version parse(const std::string& str);
39
+ static server_version parse(const std::string& str, const deployment_type deployment);
37
40
 
38
41
  [[nodiscard]] bool is_alice() const
39
42
  {
@@ -86,7 +89,7 @@ struct server_version {
86
89
 
87
90
  [[nodiscard]] bool supports_storage_backend() const
88
91
  {
89
- return is_neo();
92
+ return is_neo() && is_enterprise();
90
93
  }
91
94
 
92
95
  [[nodiscard]] bool supports_preserve_expiry() const
@@ -101,7 +104,7 @@ struct server_version {
101
104
 
102
105
  [[nodiscard]] bool supports_user_groups() const
103
106
  {
104
- return (is_mad_hatter() || is_cheshire_cat() || is_neo()) && is_enterprise();
107
+ return supports_user_management() && (is_mad_hatter() || is_cheshire_cat() || is_neo()) && is_enterprise();
105
108
  }
106
109
 
107
110
  [[nodiscard]] bool supports_query_index_management() const
@@ -146,7 +149,7 @@ struct server_version {
146
149
 
147
150
  [[nodiscard]] bool supports_eventing_functions() const
148
151
  {
149
- return is_cheshire_cat() || is_neo();
152
+ return (is_cheshire_cat() || is_neo()) && deployment == deployment_type::on_prem;
150
153
  }
151
154
 
152
155
  [[nodiscard]] bool is_enterprise() const
@@ -158,6 +161,21 @@ struct server_version {
158
161
  {
159
162
  return edition == server_edition::community;
160
163
  }
164
+
165
+ [[nodiscard]] bool supports_bucket_management() const
166
+ {
167
+ return deployment == deployment_type::on_prem;
168
+ }
169
+
170
+ [[nodiscard]] bool supports_user_management() const
171
+ {
172
+ return deployment == deployment_type::on_prem;
173
+ }
174
+
175
+ [[nodiscard]] bool supports_views() const
176
+ {
177
+ return deployment == deployment_type::on_prem;
178
+ }
161
179
  };
162
180
 
163
181
  } // namespace test::utils
@@ -51,11 +51,21 @@ test_context::load_from_environment()
51
51
  if (var != nullptr) {
52
52
  ctx.bucket = var;
53
53
  }
54
+ var = getenv("TEST_DEPLOYMENT_TYPE");
55
+ if (var != nullptr) {
56
+ if (strcmp(var, "on_prem") == 0) {
57
+ ctx.deployment = deployment_type::on_prem;
58
+ } else if (strcmp(var, "capella") == 0) {
59
+ ctx.deployment = deployment_type::capella;
60
+ } else if (strcmp(var, "elixir") == 0) {
61
+ ctx.deployment = deployment_type::elixir;
62
+ }
63
+ }
54
64
 
55
65
  // TODO: I believe this + TEST_DEVELOPER_PREVIEW will conflict
56
66
  var = getenv("TEST_SERVER_VERSION");
57
67
  if (var != nullptr) {
58
- ctx.version = server_version::parse(var);
68
+ ctx.version = server_version::parse(var, ctx.deployment);
59
69
  }
60
70
  var = getenv("TEST_DEVELOPER_PREVIEW");
61
71
  if (var != nullptr) {
@@ -33,6 +33,7 @@ struct test_context {
33
33
  std::string key_path{};
34
34
  std::string bucket{ "default" };
35
35
  server_version version{ 6, 6, 0 };
36
+ deployment_type deployment{ deployment_type::on_prem };
36
37
 
37
38
  [[nodiscard]] couchbase::cluster_credentials build_auth() const
38
39
  {
@@ -34,7 +34,7 @@ project(transactions_cxx)
34
34
  set(CB_VERSION_MAJOR 2)
35
35
  set(CB_VERSION_MINOR 0)
36
36
  set(CB_VERSION_PATCH 0)
37
- set(CB_VERSION_TWEAK "beta.3")
37
+ set(CB_VERSION_TWEAK "beta.4")
38
38
 
39
39
  find_program(GIT_EXECUTABLE NAMES git git.exe)
40
40
  macro(RUNGIT outvar)
@@ -80,7 +80,7 @@ if(NOT COUCHBASE_TXNS_CXX_CLIENT_EXTERNAL)
80
80
  if (APPLE AND NOT DEFINED OPENSSL_ROOT_DIR)
81
81
  # look in typical brew location - missed by the openssl finder
82
82
  message(STATUS "no OPENSSL_ROOT_DIR specified, using MacOS, so defaulting to homebrew location")
83
- set(OPENSSL_ROOT_DIR "/usr/local/opt/openssl@1.1", CACHE INTERNAL "")
83
+ set(OPENSSL_ROOT_DIR "/usr/local/opt/openssl@1.1" CACHE INTERNAL "")
84
84
  endif()
85
85
  message(STATUS "APPLE: '${APPLE}', SSL: '${OPENSSL_ROOT_DIR}'")
86
86
  find_package(OpenSSL REQUIRED)
@@ -17,12 +17,12 @@
17
17
 
18
18
  #pragma once
19
19
 
20
- #include <couchbase/management/design_document.hxx>
20
+ #include <couchbase/design_document_namespace.hxx>
21
21
 
22
22
  #include <fmt/core.h>
23
23
 
24
24
  template<>
25
- struct fmt::formatter<couchbase::management::views::design_document::name_space> {
25
+ struct fmt::formatter<couchbase::design_document_namespace> {
26
26
  template<typename ParseContext>
27
27
  constexpr auto parse(ParseContext& ctx)
28
28
  {
@@ -30,15 +30,15 @@ struct fmt::formatter<couchbase::management::views::design_document::name_space>
30
30
  }
31
31
 
32
32
  template<typename FormatContext>
33
- auto format(couchbase::management::views::design_document::name_space ns, FormatContext& ctx) const
33
+ auto format(couchbase::design_document_namespace ns, FormatContext& ctx) const
34
34
  {
35
35
  string_view name = "unknown";
36
36
  switch (ns) {
37
- case couchbase::management::views::design_document::name_space::development:
37
+ case couchbase::design_document_namespace::development:
38
38
  name = "development";
39
39
  break;
40
40
 
41
- case couchbase::management::views::design_document::name_space::production:
41
+ case couchbase::design_document_namespace::production:
42
42
  name = "production";
43
43
  break;
44
44
  }
@@ -26,26 +26,36 @@ namespace couchbase::operations::management
26
26
  std::error_code
27
27
  query_index_get_all_request::encode_to(encoded_request_type& encoded, couchbase::http_context& /* context */) const
28
28
  {
29
- std::string statement;
30
- if (!scope_name.empty() && !collection_name.empty()) {
31
- statement = fmt::format(
32
- R"(SELECT idx.* FROM system:indexes AS idx WHERE keyspace_id = "{}" AND bucket_id = "{}" AND scope_id = "{}" AND `using`="gsi" ORDER BY is_primary DESC, name ASC)",
33
- collection_name,
34
- bucket_name,
35
- scope_name);
29
+ std::string bucket_cond = "bucket_id = $bucket_name";
30
+ std::string scope_cond = "(" + bucket_cond + " AND scope_id = $scope_name)";
31
+ std::string collection_cond = "(" + scope_cond + " AND keyspace_id = $collection_name)";
32
+
33
+ std::string where;
34
+ if (!collection_name.empty()) {
35
+ where = collection_cond;
36
36
  } else if (!scope_name.empty()) {
37
- statement = fmt::format(
38
- R"(SELECT idx.* FROM system:indexes AS idx WHERE bucket_id = "{}" AND scope_id = "{}" AND `using`="gsi" ORDER BY is_primary DESC, name ASC)",
39
- bucket_name,
40
- scope_name);
37
+ where = scope_cond;
41
38
  } else {
42
- statement = fmt::format(
43
- R"(SELECT idx.* FROM system:indexes AS idx WHERE ((keyspace_id = "{}" AND bucket_id IS MISSING) OR (bucket_id = "{}")) AND `using`="gsi" ORDER BY is_primary DESC, name ASC)",
44
- bucket_name,
45
- bucket_name);
39
+ where = bucket_cond;
40
+ }
41
+
42
+ if (collection_name == "_default" || collection_name.empty()) {
43
+ std::string default_collection_cond = "(bucket_id IS MISSING AND keyspace_id = $bucket_name)";
44
+ where = "(" + where + " OR " + default_collection_cond + ")";
46
45
  }
46
+
47
+ std::string statement = "SELECT `idx`.* FROM system:indexes AS idx"
48
+ " WHERE " +
49
+ where +
50
+ " AND `using` = \"gsi\""
51
+ " ORDER BY is_primary DESC, name ASC";
52
+
47
53
  encoded.headers["content-type"] = "application/json";
48
- tao::json::value body{ { "statement", statement }, { "client_context_id", encoded.client_context_id } };
54
+ tao::json::value body{ { "statement", statement },
55
+ { "client_context_id", encoded.client_context_id },
56
+ { "$bucket_name", bucket_name },
57
+ { "$scope_name", scope_name },
58
+ { "$collection_name", collection_name } };
49
59
  encoded.method = "POST";
50
60
  encoded.path = "/query/service";
51
61
  encoded.body = utils::json::generate(body);
@@ -57,6 +57,21 @@ namespace transactions
57
57
  return "MAJORITY";
58
58
  }
59
59
 
60
+ static std::string durability_level_to_string_for_query(durability_level l)
61
+ {
62
+ switch (l) {
63
+ case durability_level::NONE:
64
+ return "none";
65
+ case durability_level::MAJORITY:
66
+ return "majority";
67
+ case durability_level::MAJORITY_AND_PERSIST_TO_ACTIVE:
68
+ return "majorityAndPersistToActive";
69
+ case durability_level::PERSIST_TO_MAJORITY:
70
+ return "persistToMajority";
71
+ }
72
+ return "majority";
73
+ }
74
+
60
75
  static std::string store_durability_level_to_string(durability_level l)
61
76
  {
62
77
  switch (l) {
@@ -21,6 +21,7 @@
21
21
  #include <thread>
22
22
 
23
23
  #include <couchbase/cluster.hxx>
24
+ #include <couchbase/logger/logger.hxx>
24
25
  #include <couchbase/transactions/async_attempt_context.hxx>
25
26
  #include <couchbase/transactions/attempt_context.hxx>
26
27
  #include <couchbase/transactions/exceptions.hxx>
@@ -53,15 +54,10 @@ namespace transactions
53
54
  /** @brief AsyncTransaction callback when transaction has completed */
54
55
  using txn_complete_callback = std::function<void(std::optional<transaction_exception>, std::optional<transaction_result>)>;
55
56
 
56
- /**
57
- * @brief logging levels
58
- */
59
- enum class log_level { TRACE, DEBUG, INFO, WARN, ERROR, CRITICAL, OFF };
60
-
61
57
  /**
62
58
  * @brief set log level for transactions
63
59
  */
64
- void set_transactions_log_level(log_level level);
60
+ void set_transactions_log_level(couchbase::logger::level level);
65
61
  /**
66
62
  * @mainpage
67
63
  * A transaction consists of a lambda containing all the operations you wish to perform within a transaction.
@@ -688,7 +688,7 @@ attempt_context_impl::query_begin_work(Handler&& cb)
688
688
  txdata["config"]["numAtrs"] = 1024;
689
689
  opts.raw("numatrs", jsonify(1024));
690
690
  txdata["config"]["durabilityLevel"] = durability_level_to_string(overall_.config().durability_level());
691
- opts.raw("durability_level", jsonify(durability_level_to_string(overall_.config().durability_level())));
691
+ opts.raw("durability_level", jsonify(durability_level_to_string_for_query(overall_.config().durability_level())));
692
692
  if (atr_id_) {
693
693
  txdata["atr"] = nlohmann::json::object();
694
694
  txdata["atr"]["scp"] = atr_id_->scope();
@@ -38,29 +38,32 @@ namespace transactions
38
38
  return txnlogger;
39
39
  }
40
40
 
41
- spdlog::level::level_enum cb_to_spdlog_level(couchbase::transactions::log_level level)
41
+ // TODO: better integration with client, so we don't need to repeat this private
42
+ // method.
43
+ spdlog::level::level_enum translate_level(couchbase::logger::level level)
42
44
  {
43
45
  switch (level) {
44
- case log_level::TRACE:
45
- return spdlog::level::trace;
46
- case log_level::DEBUG:
47
- return spdlog::level::debug;
48
- case log_level::INFO:
49
- return spdlog::level::info;
50
- case log_level::WARN:
51
- return spdlog::level::warn;
52
- case log_level::ERROR:
53
- return spdlog::level::err;
54
- case log_level::CRITICAL:
55
- return spdlog::level::critical;
56
- default:
57
- return spdlog::level::off;
46
+ case couchbase::logger::level::trace:
47
+ return spdlog::level::level_enum::trace;
48
+ case couchbase::logger::level::debug:
49
+ return spdlog::level::level_enum::debug;
50
+ case couchbase::logger::level::info:
51
+ return spdlog::level::level_enum::info;
52
+ case couchbase::logger::level::warn:
53
+ return spdlog::level::level_enum::warn;
54
+ case couchbase::logger::level::err:
55
+ return spdlog::level::level_enum::err;
56
+ case couchbase::logger::level::critical:
57
+ return spdlog::level::level_enum::critical;
58
+ case couchbase::logger::level::off:
59
+ return spdlog::level::level_enum::off;
58
60
  }
61
+ return spdlog::level::level_enum::trace;
59
62
  }
60
63
 
61
- void set_transactions_log_level(log_level level)
64
+ void set_transactions_log_level(couchbase::logger::level level)
62
65
  {
63
- spdlog::level::level_enum lvl = cb_to_spdlog_level(level);
66
+ spdlog::level::level_enum lvl = translate_level(level);
64
67
  txn_log->set_level(lvl);
65
68
  attempt_cleanup_log->set_level(lvl);
66
69
  lost_attempts_cleanup_log->set_level(lvl);
@@ -605,6 +605,28 @@ TEST(SimpleQueryTransactions, CanRollbackRetryBadKVReplace)
605
605
  ASSERT_EQ(c, TransactionsTestEnvironment::get_doc(id).content_as<nlohmann::json>());
606
606
  }
607
607
 
608
+ TEST(SimpleQueryTransactions, QueryCanSetAnyDurability)
609
+ {
610
+ // Just be sure that the query service understood the durability
611
+ std::list<durability_level> levels{ durability_level::NONE,
612
+ durability_level::MAJORITY,
613
+ durability_level::MAJORITY_AND_PERSIST_TO_ACTIVE,
614
+ durability_level::PERSIST_TO_MAJORITY };
615
+ auto txns = TransactionsTestEnvironment::get_transactions();
616
+ auto id = TransactionsTestEnvironment::get_document_id();
617
+ ASSERT_TRUE(TransactionsTestEnvironment::upsert_doc(id, content.dump()));
618
+ // doesn't matter if the query is read-only or not, just check that there
619
+ // is no error making the query.
620
+ auto query = fmt::format("SELECT * FROM `{}` USE KEYS '{}'", id.bucket(), id.key());
621
+ for (auto durability : levels) {
622
+ txns.run([&](attempt_context& ctx) {
623
+ ctx.query(query);
624
+ auto doc = ctx.get_optional(id);
625
+ ASSERT_TRUE(doc);
626
+ });
627
+ }
628
+ }
629
+
608
630
  int
609
631
  main(int argc, char* argv[])
610
632
  {
@@ -55,7 +55,7 @@ struct conn {
55
55
  couchbase::logger::create_console_logger();
56
56
  }
57
57
  couchbase::logger::set_log_levels(couchbase::logger::level::trace);
58
- couchbase::transactions::set_transactions_log_level(couchbase::transactions::log_level::TRACE);
58
+ couchbase::transactions::set_transactions_log_level(couchbase::logger::level::trace);
59
59
  size_t num_threads = conf.contains("io_threads") ? conf["io_threads"].get<uint32_t>() : 4;
60
60
  couchbase::transactions::txn_log->trace("using {} io completion threads", num_threads);
61
61
  for (size_t i = 0; i < num_threads; i++) {
package/dist/binding.d.ts CHANGED
@@ -665,7 +665,6 @@ export interface CppDecrementRequest {
665
665
  initial_value?: number;
666
666
  durability_level: CppProtocolDurabilityLevel;
667
667
  timeout?: CppMilliseconds;
668
- preserve_expiry: boolean;
669
668
  }
670
669
  export interface CppSearchResponse {
671
670
  status: string;
@@ -902,7 +901,6 @@ export interface CppIncrementRequest {
902
901
  initial_value?: number;
903
902
  durability_level: CppProtocolDurabilityLevel;
904
903
  timeout?: CppMilliseconds;
905
- preserve_expiry: boolean;
906
904
  }
907
905
  export interface CppManagementGroupUpsertResponse {
908
906
  errors: string[];
@@ -843,7 +843,6 @@ class Collection {
843
843
  expiry: expiry || 0,
844
844
  durability_level: (0, bindingutilities_1.durabilityToCpp)(durabilityLevel),
845
845
  timeout,
846
- preserve_expiry: false,
847
846
  partition: 0,
848
847
  opaque: 0,
849
848
  }, (cppErr, resp) => {
@@ -882,7 +881,6 @@ class Collection {
882
881
  expiry: expiry || 0,
883
882
  durability_level: (0, bindingutilities_1.durabilityToCpp)(durabilityLevel),
884
883
  timeout,
885
- preserve_expiry: false,
886
884
  partition: 0,
887
885
  opaque: 0,
888
886
  }, (cppErr, resp) => {
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import { CppConnection } from './binding';
3
4
  import { HttpErrorContext } from './errorcontexts';
4
5
  import * as events from 'events';
package/package.json CHANGED
@@ -1 +1 @@
1
- {"bugs":{"url":"http://www.couchbase.com/issues/browse/JSCBC"},"description":"The official Couchbase Node.js Client Library.","engines":{"node":">=12.0.0"},"homepage":"http://www.couchbase.com/communities/nodejs","keywords":["couchbase","libcouchbase","memcached","nosql","json","document"],"main":"dist/couchbase.js","types":"dist/couchbase.d.ts","license":"Apache-2.0","name":"couchbase","dependencies":{"bindings":"^1.5.0","cmake-js":"^6.3.0","node-addon-api":"^4.3.0","prebuild-install":"^7.1.0"},"devDependencies":{"@trivago/prettier-plugin-sort-imports":"^3.2.0","@tsconfig/node12":"^1.0.9","@types/bindings":"^1.5.1","@types/debug":"^4.1.7","@types/node":"^17.0.29","@typescript-eslint/eslint-plugin":"^5.21.0","@typescript-eslint/parser":"^5.21.0","chai":"^4.3.6","eslint":"^8.14.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jsdoc":"^39.2.9","eslint-plugin-mocha":"^10.0.4","eslint-plugin-node":"^11.1.0","expose-gc":"^1.0.0","mocha":"^9.2.2","npm-check-updates":"^12.5.9","nyc":"^15.1.0","prebuild":"^11.0.3","prettier":"^2.6.2","segfault-handler":"^1.3.0","semver":"^7.3.7","ts-mocha":"^9.0.2","ts-node":"^10.7.0","typedoc":"^0.22.15","typescript":"^4.6.3","uuid":"^8.3.2"},"repository":{"type":"git","url":"http://github.com/couchbase/couchnode.git"},"version":"4.1.0","config":{"native":false},"scripts":{"install":"prebuild-install || cmake-js compile","build":"cmake-js build && tsc","rebuild":"cmake-js rebuild && tsc","prebuild":"prebuild --backend cmake-js --verbose --strip","prepare":"tsc","build-docs":"typedoc","test":"ts-mocha test/*.test.*","test-fast":"ts-mocha test/*.test.* -ig '(slow)'","cover":"nyc ts-mocha test/*.test.*","cover-fast":"nyc ts-mocha test/*.test.* -ig '(slow)'","lint":"eslint ./lib/ ./test/","check-deps":"ncu"}}
1
+ {"bugs":{"url":"http://www.couchbase.com/issues/browse/JSCBC"},"description":"The official Couchbase Node.js Client Library.","engines":{"node":">=12.0.0"},"homepage":"http://www.couchbase.com/communities/nodejs","keywords":["couchbase","libcouchbase","memcached","nosql","json","document"],"main":"dist/couchbase.js","types":"dist/couchbase.d.ts","license":"Apache-2.0","name":"couchbase","dependencies":{"bindings":"^1.5.0","cmake-js":"^6.3.2","node-addon-api":"^5.0.0","prebuild-install":"^7.1.1"},"devDependencies":{"@trivago/prettier-plugin-sort-imports":"^3.2.0","@tsconfig/node12":"^1.0.9","@types/bindings":"^1.5.1","@types/debug":"^4.1.7","@types/node":"^17.0.41","@typescript-eslint/eslint-plugin":"^5.27.1","@typescript-eslint/parser":"^5.27.1","chai":"^4.3.6","eslint":"^8.17.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jsdoc":"^39.3.2","eslint-plugin-mocha":"^10.0.5","eslint-plugin-node":"^11.1.0","expose-gc":"^1.0.0","mocha":"^10.0.0","npm-check-updates":"^13.1.2","nyc":"^15.1.0","prebuild":"^11.0.3","prettier":"^2.6.2","segfault-handler":"^1.3.0","semver":"^7.3.7","ts-mocha":"^10.0.0","ts-node":"^10.8.1","typedoc":"^0.22.17","typescript":"^4.7.3","uuid":"^8.3.2"},"repository":{"type":"git","url":"http://github.com/couchbase/couchnode.git"},"version":"4.1.1","config":{"native":false},"scripts":{"install":"prebuild-install || cmake-js compile","build":"cmake-js build && tsc","rebuild":"cmake-js rebuild && tsc","prebuild":"prebuild --backend cmake-js --verbose --strip","prepare":"tsc","build-docs":"typedoc","test":"ts-mocha test/*.test.*","test-fast":"ts-mocha test/*.test.* -ig '(slow)'","cover":"nyc ts-mocha test/*.test.*","cover-fast":"nyc ts-mocha test/*.test.* -ig '(slow)'","lint":"eslint ./lib/ ./test/","check-deps":"ncu"}}