couchbase 4.1.0 → 4.1.1

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 (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"}}