couchbase 4.1.0 → 4.1.1
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +8 -0
- package/deps/couchbase-cxx-client/.github/workflows/linters.yml +2 -2
- package/deps/couchbase-cxx-client/.github/workflows/sanitizers.yml +18 -2
- package/deps/couchbase-cxx-client/.github/workflows/tests.yml +14 -34
- package/deps/couchbase-cxx-client/.github/workflows/windows.yml +13 -15
- package/deps/couchbase-cxx-client/CMakeLists.txt +6 -1
- package/deps/couchbase-cxx-client/bin/build-tests +3 -0
- package/deps/couchbase-cxx-client/bin/build-tests.rb +3 -0
- package/deps/couchbase-cxx-client/bin/init-cluster +1 -1
- package/deps/couchbase-cxx-client/bin/run-tests +1 -1
- package/deps/couchbase-cxx-client/cmake/StandardProjectSettings.cmake +1 -1
- package/deps/couchbase-cxx-client/couchbase/cluster.hxx +25 -6
- package/deps/couchbase-cxx-client/couchbase/io/mcbp_session.hxx +21 -7
- package/deps/couchbase-cxx-client/couchbase/meta/version.cxx +7 -0
- package/deps/couchbase-cxx-client/couchbase/operations/document_decrement.cxx +0 -3
- package/deps/couchbase-cxx-client/couchbase/operations/document_decrement.hxx +0 -1
- package/deps/couchbase-cxx-client/couchbase/operations/document_increment.cxx +0 -3
- package/deps/couchbase-cxx-client/couchbase/operations/document_increment.hxx +0 -1
- package/deps/couchbase-cxx-client/couchbase/operations/management/analytics_dataset_get_all.cxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/operations/management/analytics_get_pending_mutations.cxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/operations/management/analytics_get_pending_mutations.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/operations/management/query_index_drop.cxx +4 -3
- package/deps/couchbase-cxx-client/couchbase/origin.hxx +10 -0
- package/deps/couchbase-cxx-client/couchbase/protocol/cmd_decrement.cxx +3 -8
- package/deps/couchbase-cxx-client/couchbase/protocol/cmd_decrement.hxx +0 -2
- package/deps/couchbase-cxx-client/couchbase/protocol/cmd_increment.cxx +0 -9
- package/deps/couchbase-cxx-client/couchbase/protocol/cmd_increment.hxx +0 -2
- package/deps/couchbase-cxx-client/couchbase/utils/json_streaming_lexer.cxx +6 -2
- package/deps/couchbase-cxx-client/test/test_integration_collections.cxx +4 -6
- package/deps/couchbase-cxx-client/test/test_integration_connect.cxx +4 -0
- package/deps/couchbase-cxx-client/test/test_integration_management.cxx +194 -138
- package/deps/couchbase-cxx-client/test/test_integration_query.cxx +26 -10
- package/deps/couchbase-cxx-client/test/test_unit_json_streaming_lexer.cxx +119 -0
- package/deps/couchbase-cxx-client/test/utils/integration_test_guard.cxx +1 -1
- package/deps/couchbase-cxx-client/test/utils/server_version.cxx +2 -1
- package/deps/couchbase-cxx-client/test/utils/server_version.hxx +22 -4
- package/deps/couchbase-cxx-client/test/utils/test_context.cxx +11 -1
- package/deps/couchbase-cxx-client/test/utils/test_context.hxx +1 -0
- package/deps/couchbase-transactions-cxx/CMakeLists.txt +2 -2
- package/deps/couchbase-transactions-cxx/deps/couchbase-cxx-client/couchbase/{management/design_document_fmt.hxx → design_document_namespace_fmt.hxx} +5 -5
- package/deps/couchbase-transactions-cxx/deps/couchbase-cxx-client/couchbase/operations/management/query_index_get_all.cxx +26 -16
- package/deps/couchbase-transactions-cxx/include/couchbase/transactions/durability_level.hxx +15 -0
- package/deps/couchbase-transactions-cxx/include/couchbase/transactions.hxx +2 -6
- package/deps/couchbase-transactions-cxx/src/transactions/attempt_context_impl.cxx +1 -1
- package/deps/couchbase-transactions-cxx/src/transactions/logging.cxx +20 -17
- package/deps/couchbase-transactions-cxx/tests/transactions/simple_t.cpp +22 -0
- package/deps/couchbase-transactions-cxx/tests/transactions/transactions_env.h +1 -1
- package/dist/binding.d.ts +0 -2
- package/dist/collection.js +0 -2
- package/dist/httpexecutor.d.ts +1 -0
- package/package.json +1 -1
- package/src/jstocbpp_autogen.hpp +3 -9
- package/deps/couchbase-cxx-client/.github/workflows/benchmarks.yml +0 -94
- 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
|
-
|
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
|
-
|
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) {
|
@@ -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.
|
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"
|
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/
|
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::
|
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::
|
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::
|
37
|
+
case couchbase::design_document_namespace::development:
|
38
38
|
name = "development";
|
39
39
|
break;
|
40
40
|
|
41
|
-
case couchbase::
|
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
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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 },
|
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(
|
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(
|
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
|
-
|
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
|
45
|
-
return spdlog::level::trace;
|
46
|
-
case
|
47
|
-
return spdlog::level::debug;
|
48
|
-
case
|
49
|
-
return spdlog::level::info;
|
50
|
-
case
|
51
|
-
return spdlog::level::warn;
|
52
|
-
case
|
53
|
-
return spdlog::level::err;
|
54
|
-
case
|
55
|
-
return spdlog::level::critical;
|
56
|
-
|
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(
|
64
|
+
void set_transactions_log_level(couchbase::logger::level level)
|
62
65
|
{
|
63
|
-
spdlog::level::level_enum lvl =
|
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::
|
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[];
|
package/dist/collection.js
CHANGED
@@ -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) => {
|
package/dist/httpexecutor.d.ts
CHANGED
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.
|
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"}}
|