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