couchbase 3.4.0 → 3.4.2
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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/ext/couchbase/CMakeLists.txt +10 -3
- data/ext/couchbase/cmake/CompilerWarnings.cmake +12 -4
- data/ext/couchbase/cmake/Documentation.cmake +4 -3
- data/ext/couchbase/cmake/OpenSSL.cmake +52 -7
- data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +4 -0
- data/ext/couchbase/cmake/VersionInfo.cmake +39 -3
- data/ext/couchbase/cmake/test_openssl.cxx +7 -0
- data/ext/couchbase/core/cluster_options.hxx +0 -1
- data/ext/couchbase/core/config_profile.cxx +23 -1
- data/ext/couchbase/core/config_profile.hxx +2 -12
- data/ext/couchbase/core/crypto/CMakeLists.txt +5 -1
- data/ext/couchbase/core/impl/analytics.cxx +236 -0
- data/ext/couchbase/core/impl/cluster.cxx +0 -1
- data/ext/couchbase/core/impl/collection_query_index_manager.cxx +3 -3
- data/ext/couchbase/core/impl/dns_srv_tracker.cxx +5 -3
- data/ext/couchbase/core/impl/get_all_query_indexes.cxx +3 -3
- data/ext/couchbase/core/impl/query.cxx +5 -5
- data/ext/couchbase/core/impl/transaction_get_result.cxx +54 -0
- data/ext/couchbase/core/io/dns_client.cxx +225 -0
- data/ext/couchbase/core/io/dns_client.hxx +19 -188
- data/ext/couchbase/core/meta/CMakeLists.txt +7 -5
- data/ext/couchbase/core/meta/version.cxx +19 -0
- data/ext/couchbase/core/operations/document_search.cxx +5 -2
- data/ext/couchbase/core/operations/document_search.hxx +0 -1
- data/ext/couchbase/core/transactions/active_transaction_record.hxx +2 -2
- data/ext/couchbase/core/transactions/atr_cleanup_entry.cxx +1 -0
- data/ext/couchbase/core/transactions/attempt_context_impl.cxx +65 -31
- data/ext/couchbase/core/transactions/attempt_context_impl.hxx +44 -23
- data/ext/couchbase/core/transactions/forward_compat.hxx +2 -2
- data/ext/couchbase/core/transactions/internal/transaction_context.hxx +13 -13
- data/ext/couchbase/core/transactions/internal/transaction_fields.hxx +1 -0
- data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +7 -1
- data/ext/couchbase/core/transactions/staged_mutation.cxx +1 -1
- data/ext/couchbase/core/transactions/staged_mutation.hxx +12 -2
- data/ext/couchbase/core/transactions/transaction_context.cxx +9 -11
- data/ext/couchbase/core/transactions/transaction_get_result.cxx +41 -31
- data/ext/couchbase/core/transactions/transaction_get_result.hxx +7 -3
- data/ext/couchbase/core/transactions/transaction_links.hxx +13 -1
- data/ext/couchbase/core/transactions/transactions_cleanup.cxx +144 -155
- data/ext/couchbase/core/transactions/waitable_op_list.hxx +1 -0
- data/ext/couchbase/core/utils/connection_string.cxx +10 -3
- data/ext/couchbase/core/utils/connection_string.hxx +3 -3
- data/ext/couchbase/couchbase/analytics_error_context.hxx +143 -0
- data/ext/couchbase/couchbase/analytics_meta_data.hxx +155 -0
- data/ext/couchbase/couchbase/analytics_metrics.hxx +163 -0
- data/ext/couchbase/couchbase/analytics_options.hxx +359 -0
- data/ext/couchbase/couchbase/analytics_result.hxx +102 -0
- data/ext/couchbase/couchbase/analytics_scan_consistency.hxx +46 -0
- data/ext/couchbase/couchbase/analytics_status.hxx +41 -0
- data/ext/couchbase/couchbase/analytics_warning.hxx +85 -0
- data/ext/couchbase/couchbase/cluster.hxx +35 -2
- data/ext/couchbase/couchbase/cluster_options.hxx +10 -10
- data/ext/couchbase/couchbase/collection.hxx +22 -17
- data/ext/couchbase/couchbase/collection_query_index_manager.hxx +1 -1
- data/ext/couchbase/couchbase/common_options.hxx +1 -1
- data/ext/couchbase/couchbase/configuration_profile.hxx +1 -1
- data/ext/couchbase/couchbase/configuration_profiles_registry.hxx +0 -1
- data/ext/couchbase/couchbase/create_primary_query_index_options.hxx +1 -1
- data/ext/couchbase/couchbase/drop_primary_query_index_options.hxx +1 -1
- data/ext/couchbase/couchbase/drop_query_index_options.hxx +1 -1
- data/ext/couchbase/couchbase/fmt/analytics_status.hxx +76 -0
- data/ext/couchbase/couchbase/fmt/cas.hxx +12 -0
- data/ext/couchbase/couchbase/fmt/durability_level.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/key_value_extended_error_info.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/key_value_status_code.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/mutation_token.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/query_scan_consistency.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/query_status.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/retry_reason.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/tls_verify_mode.hxx +6 -0
- data/ext/couchbase/couchbase/get_all_query_indexes_options.hxx +5 -4
- data/ext/couchbase/couchbase/query_index_manager.hxx +4 -2
- data/ext/couchbase/couchbase/query_options.hxx +0 -1
- data/ext/couchbase/couchbase/scope.hxx +34 -1
- data/ext/couchbase/couchbase/subdoc/array_add_unique.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/array_append.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/array_insert.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/array_prepend.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/count.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/counter.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/exists.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/get.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/insert.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/remove.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/replace.hxx +3 -1
- data/ext/couchbase/couchbase/subdoc/upsert.hxx +2 -0
- data/ext/couchbase/couchbase/transaction_op_error_context.hxx +4 -4
- data/ext/couchbase/couchbase/transactions/attempt_context.hxx +1 -1
- data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +36 -51
- data/ext/couchbase/couchbase/transactions/transactions_config.hxx +1 -1
- data/ext/couchbase/test/CMakeLists.txt +3 -2
- data/ext/couchbase/test/test_helper.hxx +1 -1
- data/ext/couchbase/test/test_integration_analytics.cxx +289 -13
- data/ext/couchbase/test/test_integration_crud.cxx +8 -1
- data/ext/couchbase/test/test_integration_examples.cxx +182 -0
- data/ext/couchbase/test/test_integration_management.cxx +15 -3
- data/ext/couchbase/test/test_integration_search.cxx +601 -0
- data/ext/couchbase/test/test_transaction_transaction_simple.cxx +73 -0
- data/ext/couchbase/test/test_unit_config_profiles.cxx +12 -12
- data/ext/couchbase/test/test_unit_connection_string.cxx +35 -0
- data/ext/couchbase/test/test_unit_transaction_utils.cxx +76 -19
- data/ext/couchbase/third_party/snappy/CMakeLists.txt +150 -27
- data/ext/couchbase/third_party/snappy/cmake/config.h.in +28 -24
- data/ext/couchbase/third_party/snappy/snappy-internal.h +189 -25
- data/ext/couchbase/third_party/snappy/snappy-sinksource.cc +26 -9
- data/ext/couchbase/third_party/snappy/snappy-sinksource.h +11 -11
- data/ext/couchbase/third_party/snappy/snappy-stubs-internal.cc +1 -1
- data/ext/couchbase/third_party/snappy/snappy-stubs-internal.h +227 -308
- data/ext/couchbase/third_party/snappy/snappy-stubs-public.h.in +0 -11
- data/ext/couchbase/third_party/snappy/snappy.cc +1176 -410
- data/ext/couchbase/third_party/snappy/snappy.h +19 -4
- data/ext/couchbase.cxx +506 -26
- data/ext/extconf.rb +2 -1
- data/ext/revisions.rb +3 -2
- data/lib/couchbase/binary_collection.rb +4 -4
- data/lib/couchbase/cluster.rb +13 -9
- data/lib/couchbase/cluster_registry.rb +7 -2
- data/lib/couchbase/collection.rb +5 -0
- data/lib/couchbase/configuration.rb +3 -4
- data/lib/couchbase/errors.rb +10 -0
- data/lib/couchbase/management/collection_query_index_manager.rb +183 -0
- data/lib/couchbase/management/query_index_manager.rb +35 -3
- data/lib/couchbase/management.rb +1 -0
- data/lib/couchbase/options.rb +87 -5
- data/lib/couchbase/search_options.rb +158 -240
- data/lib/couchbase/version.rb +1 -1
- metadata +21 -6
- data/ext/couchbase/core/CMakeLists.txt +0 -0
|
@@ -56,7 +56,9 @@ class replace
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
private:
|
|
59
|
+
#ifndef COUCHBASE_CXX_CLIENT_DOXYGEN
|
|
59
60
|
friend couchbase::mutate_in_specs;
|
|
61
|
+
#endif
|
|
60
62
|
|
|
61
63
|
replace(std::string path, std::vector<std::byte> value)
|
|
62
64
|
: path_(std::move(path))
|
|
@@ -86,4 +88,4 @@ class replace
|
|
|
86
88
|
bool expand_macro_{ false };
|
|
87
89
|
};
|
|
88
90
|
} // namespace subdoc
|
|
89
|
-
} // namespace couchbase
|
|
91
|
+
} // namespace couchbase
|
|
@@ -46,13 +46,13 @@ class transaction_op_error_context
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
|
-
* The error_code associated with this error context.
|
|
49
|
+
* The error_code associated with this error context.
|
|
50
50
|
*
|
|
51
51
|
* Note that some query errors are not _transaction_ errors, so this error code will be 0, but there will be
|
|
52
|
-
* a @ref
|
|
52
|
+
* a @ref cause() with a @ref query_error_context in it. These errors do not rollback a
|
|
53
53
|
* transaction. If you want to roll it back, raise an exception.
|
|
54
54
|
*
|
|
55
|
-
* @return a
|
|
55
|
+
* @return a error code, if any.
|
|
56
56
|
*/
|
|
57
57
|
[[nodiscard]] std::error_code ec() const
|
|
58
58
|
{
|
|
@@ -60,7 +60,7 @@ class transaction_op_error_context
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
* The underlying cause of this error. This can be either a @ref
|
|
63
|
+
* The underlying cause of this error. This can be either a @ref key_value_error_context or a @ref query_error_context.
|
|
64
64
|
*
|
|
65
65
|
* @return the error_context associated with the underlying cause of this error.
|
|
66
66
|
*/
|
|
@@ -33,7 +33,7 @@ class attempt_context
|
|
|
33
33
|
const Content& content)
|
|
34
34
|
{
|
|
35
35
|
if constexpr (std::is_same_v<Content, std::vector<std::byte>>) {
|
|
36
|
-
return insert_raw(
|
|
36
|
+
return insert_raw(coll, id, content);
|
|
37
37
|
} else {
|
|
38
38
|
return insert_raw(coll, id, codec::tao_json_serializer::serialize(content));
|
|
39
39
|
}
|
|
@@ -24,36 +24,31 @@
|
|
|
24
24
|
#include <couchbase/result.hxx>
|
|
25
25
|
#include <couchbase/transaction_op_error_context.hxx>
|
|
26
26
|
|
|
27
|
+
// forward declarations...
|
|
28
|
+
namespace couchbase::core::transactions
|
|
29
|
+
{
|
|
30
|
+
class transaction_get_result;
|
|
31
|
+
class transaction_links;
|
|
32
|
+
class document_metadata;
|
|
33
|
+
} // namespace couchbase::core::transactions
|
|
34
|
+
|
|
27
35
|
namespace couchbase::transactions
|
|
28
36
|
{
|
|
29
37
|
|
|
30
|
-
class transaction_get_result
|
|
38
|
+
class transaction_get_result
|
|
31
39
|
{
|
|
32
|
-
|
|
33
|
-
std::string bucket_{};
|
|
34
|
-
std::string scope_{};
|
|
35
|
-
std::string collection_{};
|
|
36
|
-
std::string key_{};
|
|
37
|
-
std::vector<std::byte> content_{};
|
|
40
|
+
friend class couchbase::core::transactions::transaction_get_result;
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
transaction_get_result
|
|
41
|
-
|
|
42
|
-
transaction_get_result(std::
|
|
43
|
-
|
|
44
|
-
std::string collection,
|
|
45
|
-
std::string key,
|
|
46
|
-
couchbase::cas cas,
|
|
47
|
-
std::vector<std::byte> content)
|
|
48
|
-
: result(cas)
|
|
49
|
-
, bucket_(std::move(bucket))
|
|
50
|
-
, scope_(std::move(scope))
|
|
51
|
-
, collection_(std::move(collection))
|
|
52
|
-
, key_(std::move(key))
|
|
53
|
-
, content_(std::move(content))
|
|
42
|
+
private:
|
|
43
|
+
std::shared_ptr<couchbase::core::transactions::transaction_get_result> base_{};
|
|
44
|
+
|
|
45
|
+
transaction_get_result(std::shared_ptr<couchbase::core::transactions::transaction_get_result> base)
|
|
46
|
+
: base_(base)
|
|
54
47
|
{
|
|
55
48
|
}
|
|
56
49
|
|
|
50
|
+
public:
|
|
51
|
+
transaction_get_result();
|
|
57
52
|
/**
|
|
58
53
|
* Content of the document.
|
|
59
54
|
*
|
|
@@ -62,7 +57,7 @@ class transaction_get_result : public result
|
|
|
62
57
|
template<typename Content>
|
|
63
58
|
[[nodiscard]] Content content() const
|
|
64
59
|
{
|
|
65
|
-
return codec::tao_json_serializer::deserialize<Content>(
|
|
60
|
+
return codec::tao_json_serializer::deserialize<Content>(content());
|
|
66
61
|
}
|
|
67
62
|
|
|
68
63
|
/**
|
|
@@ -70,64 +65,54 @@ class transaction_get_result : public result
|
|
|
70
65
|
*
|
|
71
66
|
* @return content
|
|
72
67
|
*/
|
|
73
|
-
[[nodiscard]] const std::vector<std::byte>& content() const
|
|
74
|
-
|
|
75
|
-
return content_;
|
|
76
|
-
}
|
|
68
|
+
[[nodiscard]] const std::vector<std::byte>& content() const;
|
|
69
|
+
|
|
77
70
|
/**
|
|
78
71
|
* Copy content into document
|
|
79
72
|
* @param content
|
|
80
73
|
*/
|
|
81
|
-
void content(std::vector<std::byte> content)
|
|
82
|
-
|
|
83
|
-
content_ = std::move(content);
|
|
84
|
-
}
|
|
74
|
+
void content(std::vector<std::byte> content);
|
|
75
|
+
|
|
85
76
|
/**
|
|
86
77
|
* Move content into document
|
|
87
78
|
*
|
|
88
79
|
* @param content
|
|
89
80
|
*/
|
|
90
|
-
void content(std::vector<std::byte>&& content)
|
|
91
|
-
{
|
|
92
|
-
content_ = std::move(content);
|
|
93
|
-
}
|
|
81
|
+
void content(std::vector<std::byte>&& content);
|
|
94
82
|
|
|
95
83
|
/**
|
|
96
84
|
* Get document id.
|
|
97
85
|
*
|
|
98
86
|
* @return the id of this document.
|
|
99
87
|
*/
|
|
100
|
-
[[nodiscard]] const std::string key() const
|
|
101
|
-
{
|
|
102
|
-
return key_;
|
|
103
|
-
}
|
|
88
|
+
[[nodiscard]] const std::string key() const;
|
|
104
89
|
|
|
105
90
|
/**
|
|
106
91
|
* Get the name of the bucket this document is in.
|
|
107
92
|
*
|
|
108
93
|
* @return name of the bucket which contains the document.
|
|
109
94
|
*/
|
|
110
|
-
[[nodiscard]] const std::string bucket() const
|
|
111
|
-
|
|
112
|
-
return bucket_;
|
|
113
|
-
}
|
|
95
|
+
[[nodiscard]] const std::string bucket() const;
|
|
96
|
+
|
|
114
97
|
/**
|
|
115
98
|
* Get the name of the scope this document is in.
|
|
116
99
|
*
|
|
117
100
|
* @return name of the scope which contains the document.
|
|
118
101
|
*/
|
|
119
|
-
[[nodiscard]] const std::string scope() const
|
|
120
|
-
|
|
121
|
-
return scope_;
|
|
122
|
-
}
|
|
102
|
+
[[nodiscard]] const std::string scope() const;
|
|
103
|
+
|
|
123
104
|
/**
|
|
124
105
|
* Get the name of the collection this document is in.
|
|
125
106
|
*
|
|
126
107
|
* @return name of the collection which contains the document.
|
|
127
108
|
*/
|
|
128
|
-
[[nodiscard]] const std::string collection() const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
109
|
+
[[nodiscard]] const std::string collection() const;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get the CAS fot this document
|
|
113
|
+
*
|
|
114
|
+
* @return the CAS of the document.
|
|
115
|
+
*/
|
|
116
|
+
[[nodiscard]] const couchbase::cas cas() const;
|
|
132
117
|
};
|
|
133
118
|
} // namespace couchbase::transactions
|
|
@@ -115,7 +115,7 @@ class transactions_config
|
|
|
115
115
|
/**
|
|
116
116
|
* @brief Set the expiration time for transactions.
|
|
117
117
|
*
|
|
118
|
-
* @param duration desired expiration for transactions. see @expiration_time().
|
|
118
|
+
* @param duration desired expiration for transactions. see @ref expiration_time().
|
|
119
119
|
* @return reference to this, so calls can be chained.
|
|
120
120
|
*/
|
|
121
121
|
template<typename T>
|
|
@@ -16,6 +16,7 @@ integration_test(tracer)
|
|
|
16
16
|
integration_test(meter)
|
|
17
17
|
integration_test(transcoders)
|
|
18
18
|
integration_test(range_scan)
|
|
19
|
+
integration_test(search)
|
|
19
20
|
|
|
20
21
|
unit_test(connection_string)
|
|
21
22
|
unit_test(utils)
|
|
@@ -28,8 +29,6 @@ target_link_libraries(test_unit_jsonsl jsonsl)
|
|
|
28
29
|
|
|
29
30
|
integration_benchmark(get)
|
|
30
31
|
|
|
31
|
-
add_subdirectory(tools)
|
|
32
|
-
|
|
33
32
|
transaction_test(transaction_context)
|
|
34
33
|
transaction_test(transaction_simple)
|
|
35
34
|
transaction_test(transaction_simple_async)
|
|
@@ -39,3 +38,5 @@ transaction_test(transaction_public_async_api)
|
|
|
39
38
|
unit_test(transaction_logging)
|
|
40
39
|
unit_test(transaction_utils)
|
|
41
40
|
unit_test(waitable_op_list)
|
|
41
|
+
|
|
42
|
+
integration_test(examples)
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
#include "core/operations/management/analytics.hxx"
|
|
19
19
|
#include "core/operations/management/collection_create.hxx"
|
|
20
|
-
#include "core/operations/management/
|
|
20
|
+
#include "core/operations/management/collections.hxx"
|
|
21
21
|
#include "test_helper_integration.hxx"
|
|
22
22
|
|
|
23
23
|
TEST_CASE("integration: analytics query")
|
|
@@ -78,7 +78,7 @@ TEST_CASE("integration: analytics query")
|
|
|
78
78
|
REQUIRE(test::utils::wait_until([&]() {
|
|
79
79
|
couchbase::core::operations::analytics_request req{};
|
|
80
80
|
req.statement = fmt::format(R"(SELECT testkey FROM `Default`.`{}` WHERE testkey = ?)", dataset_name);
|
|
81
|
-
req.positional_parameters.emplace_back(couchbase::core::
|
|
81
|
+
req.positional_parameters.emplace_back(couchbase::core::utils::json::generate(test_value));
|
|
82
82
|
resp = test::utils::execute(integration.cluster, req);
|
|
83
83
|
return resp.rows.size() == 1;
|
|
84
84
|
}));
|
|
@@ -130,10 +130,30 @@ TEST_CASE("integration: analytics query")
|
|
|
130
130
|
|
|
131
131
|
SECTION("consistency")
|
|
132
132
|
{
|
|
133
|
-
couchbase::core::operations::
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
couchbase::core::operations::analytics_response resp{};
|
|
134
|
+
CHECK(test::utils::wait_until([&]() {
|
|
135
|
+
/*
|
|
136
|
+
* In consistency test, always do fresh mutation
|
|
137
|
+
*/
|
|
138
|
+
test_value = test::utils::uniq_id("value");
|
|
139
|
+
value = couchbase::core::utils::json::generate({ { "testkey", test_value } });
|
|
140
|
+
{
|
|
141
|
+
auto id = couchbase::core::document_id(integration.ctx.bucket, "_default", "_default", key);
|
|
142
|
+
couchbase::core::operations::upsert_request req{ id, couchbase::core::utils::to_binary(value) };
|
|
143
|
+
REQUIRE_SUCCESS(test::utils::execute(integration.cluster, req).ctx.ec());
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
couchbase::core::operations::analytics_request req{};
|
|
147
|
+
req.statement = fmt::format(R"(SELECT testkey FROM `Default`.`{}` WHERE testkey = "{}")", dataset_name, test_value);
|
|
148
|
+
req.scan_consistency = couchbase::core::analytics_scan_consistency::request_plus;
|
|
149
|
+
resp = test::utils::execute(integration.cluster, req);
|
|
150
|
+
/* Analytics might give us code 23027, ignore it here
|
|
151
|
+
*
|
|
152
|
+
* "errors": [{"code": 23027, "msg": "Bucket default on link Default.Local is not connected"} ],
|
|
153
|
+
*/
|
|
154
|
+
return resp.ctx.first_error_code != 23027;
|
|
155
|
+
}));
|
|
156
|
+
|
|
137
157
|
REQUIRE_SUCCESS(resp.ctx.ec);
|
|
138
158
|
REQUIRE(resp.rows.size() == 1);
|
|
139
159
|
REQUIRE(resp.rows[0] == value);
|
|
@@ -185,13 +205,15 @@ TEST_CASE("integration: analytics scope query")
|
|
|
185
205
|
REQUIRE(created);
|
|
186
206
|
}
|
|
187
207
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
208
|
+
CHECK(test::utils::wait_until(
|
|
209
|
+
[&]() {
|
|
210
|
+
couchbase::core::operations::analytics_request req{};
|
|
211
|
+
req.statement =
|
|
212
|
+
fmt::format("ALTER COLLECTION `{}`.`{}`.`{}` ENABLE ANALYTICS", integration.ctx.bucket, scope_name, collection_name);
|
|
213
|
+
auto resp = test::utils::execute(integration.cluster, req);
|
|
214
|
+
return !resp.ctx.ec;
|
|
215
|
+
},
|
|
216
|
+
std::chrono::minutes{ 5 }));
|
|
195
217
|
|
|
196
218
|
auto key = test::utils::uniq_id("key");
|
|
197
219
|
auto test_value = test::utils::uniq_id("value");
|
|
@@ -259,3 +281,257 @@ TEST_CASE("unit: analytics query")
|
|
|
259
281
|
REQUIRE(http_req.headers.find("analytics-priority") == http_req.headers.end());
|
|
260
282
|
}
|
|
261
283
|
}
|
|
284
|
+
|
|
285
|
+
TEST_CASE("integration: public API analytics query")
|
|
286
|
+
{
|
|
287
|
+
test::utils::integration_test_guard integration;
|
|
288
|
+
|
|
289
|
+
if (!integration.cluster_version().supports_analytics()) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
auto cluster = couchbase::cluster(integration.cluster);
|
|
294
|
+
auto bucket = cluster.bucket(integration.ctx.bucket);
|
|
295
|
+
auto collection = bucket.default_collection();
|
|
296
|
+
|
|
297
|
+
auto dataset_name = test::utils::uniq_id("dataset");
|
|
298
|
+
|
|
299
|
+
{
|
|
300
|
+
couchbase::core::operations::management::analytics_dataset_create_request req{};
|
|
301
|
+
req.dataset_name = dataset_name;
|
|
302
|
+
req.bucket_name = integration.ctx.bucket;
|
|
303
|
+
auto resp = test::utils::execute(integration.cluster, req);
|
|
304
|
+
REQUIRE_SUCCESS(resp.ctx.ec);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
{
|
|
308
|
+
couchbase::core::operations::management::analytics_link_connect_request req{};
|
|
309
|
+
req.force = true;
|
|
310
|
+
auto resp = test::utils::execute(integration.cluster, req);
|
|
311
|
+
REQUIRE_SUCCESS(resp.ctx.ec);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
auto key = test::utils::uniq_id("key");
|
|
315
|
+
auto test_value = test::utils::uniq_id("value");
|
|
316
|
+
tao::json::value document = {
|
|
317
|
+
{ "testkey", test_value },
|
|
318
|
+
};
|
|
319
|
+
{
|
|
320
|
+
auto [ctx, resp] = collection.upsert(key, document).get();
|
|
321
|
+
REQUIRE_SUCCESS(ctx.ec());
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
SECTION("simple query")
|
|
325
|
+
{
|
|
326
|
+
couchbase::analytics_result resp{};
|
|
327
|
+
couchbase::analytics_error_context ctx{};
|
|
328
|
+
CHECK(test::utils::wait_until([&]() {
|
|
329
|
+
std::tie(ctx, resp) =
|
|
330
|
+
cluster.analytics_query(fmt::format(R"(SELECT testkey FROM `Default`.`{}` WHERE testkey = "{}")", dataset_name, test_value))
|
|
331
|
+
.get();
|
|
332
|
+
return !ctx.ec() && resp.meta_data().metrics().result_count() == 1;
|
|
333
|
+
}));
|
|
334
|
+
REQUIRE_SUCCESS(ctx.ec());
|
|
335
|
+
REQUIRE_FALSE(resp.meta_data().request_id().empty());
|
|
336
|
+
REQUIRE_FALSE(resp.meta_data().client_context_id().empty());
|
|
337
|
+
REQUIRE(resp.meta_data().status() == couchbase::analytics_status::success);
|
|
338
|
+
auto rows = resp.rows_as_json();
|
|
339
|
+
REQUIRE(rows.size() == 1);
|
|
340
|
+
REQUIRE(rows[0] == document);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
SECTION("positional params")
|
|
344
|
+
{
|
|
345
|
+
couchbase::analytics_result resp{};
|
|
346
|
+
couchbase::analytics_error_context ctx{};
|
|
347
|
+
CHECK(test::utils::wait_until([&]() {
|
|
348
|
+
std::tie(ctx, resp) = cluster
|
|
349
|
+
.analytics_query(fmt::format(R"(SELECT testkey FROM `Default`.`{}` WHERE testkey = ?)", dataset_name),
|
|
350
|
+
couchbase::analytics_options{}.positional_parameters(test_value))
|
|
351
|
+
.get();
|
|
352
|
+
return !ctx.ec() && resp.meta_data().metrics().result_count() == 1;
|
|
353
|
+
}));
|
|
354
|
+
REQUIRE_SUCCESS(ctx.ec());
|
|
355
|
+
auto rows = resp.rows_as_json();
|
|
356
|
+
REQUIRE(rows.size() == 1);
|
|
357
|
+
REQUIRE(rows[0] == document);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
SECTION("named params")
|
|
361
|
+
{
|
|
362
|
+
couchbase::analytics_result resp{};
|
|
363
|
+
couchbase::analytics_error_context ctx{};
|
|
364
|
+
CHECK(test::utils::wait_until([&]() {
|
|
365
|
+
std::tie(ctx, resp) =
|
|
366
|
+
cluster
|
|
367
|
+
.analytics_query(fmt::format(R"(SELECT testkey FROM `Default`.`{}` WHERE testkey = $testkey)", dataset_name),
|
|
368
|
+
couchbase::analytics_options{}.named_parameters(std::pair{ "testkey", test_value }))
|
|
369
|
+
.get();
|
|
370
|
+
return !ctx.ec() && resp.meta_data().metrics().result_count() == 1;
|
|
371
|
+
}));
|
|
372
|
+
REQUIRE_SUCCESS(ctx.ec());
|
|
373
|
+
auto rows = resp.rows_as_json();
|
|
374
|
+
REQUIRE(rows.size() == 1);
|
|
375
|
+
REQUIRE(rows[0] == document);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
SECTION("named params preformatted")
|
|
379
|
+
{
|
|
380
|
+
couchbase::analytics_result resp{};
|
|
381
|
+
couchbase::analytics_error_context ctx{};
|
|
382
|
+
CHECK(test::utils::wait_until([&]() {
|
|
383
|
+
std::tie(ctx, resp) =
|
|
384
|
+
cluster
|
|
385
|
+
.analytics_query(fmt::format(R"(SELECT testkey FROM `Default`.`{}` WHERE testkey = $testkey)", dataset_name),
|
|
386
|
+
couchbase::analytics_options{}.encoded_named_parameters(
|
|
387
|
+
{ { "testkey", couchbase::core::utils::json::generate_binary(test_value) } }))
|
|
388
|
+
.get();
|
|
389
|
+
return !ctx.ec() && resp.meta_data().metrics().result_count() == 1;
|
|
390
|
+
}));
|
|
391
|
+
REQUIRE_SUCCESS(ctx.ec());
|
|
392
|
+
auto rows = resp.rows_as_json();
|
|
393
|
+
REQUIRE(rows.size() == 1);
|
|
394
|
+
REQUIRE(rows[0] == document);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
SECTION("raw")
|
|
398
|
+
{
|
|
399
|
+
couchbase::analytics_result resp{};
|
|
400
|
+
couchbase::analytics_error_context ctx{};
|
|
401
|
+
CHECK(test::utils::wait_until([&]() {
|
|
402
|
+
std::tie(ctx, resp) =
|
|
403
|
+
cluster
|
|
404
|
+
.analytics_query(fmt::format(R"(SELECT testkey FROM `Default`.`{}` WHERE testkey = $testkey)", dataset_name),
|
|
405
|
+
couchbase::analytics_options{}.raw("$testkey", test_value))
|
|
406
|
+
.get();
|
|
407
|
+
return !ctx.ec() && resp.meta_data().metrics().result_count() == 1;
|
|
408
|
+
}));
|
|
409
|
+
REQUIRE_SUCCESS(ctx.ec());
|
|
410
|
+
auto rows = resp.rows_as_json();
|
|
411
|
+
REQUIRE(rows.size() == 1);
|
|
412
|
+
REQUIRE(rows[0] == document);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
SECTION("consistency")
|
|
416
|
+
{
|
|
417
|
+
couchbase::analytics_result resp{};
|
|
418
|
+
couchbase::analytics_error_context ctx{};
|
|
419
|
+
CHECK(test::utils::wait_until([&]() {
|
|
420
|
+
/*
|
|
421
|
+
* In consistency test, always do fresh mutation
|
|
422
|
+
*/
|
|
423
|
+
test_value = test::utils::uniq_id("value");
|
|
424
|
+
document = {
|
|
425
|
+
{ "testkey", test_value },
|
|
426
|
+
};
|
|
427
|
+
{
|
|
428
|
+
auto [ctx2, _] = collection.upsert(key, document).get();
|
|
429
|
+
REQUIRE_SUCCESS(ctx2.ec());
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
std::tie(ctx, resp) =
|
|
433
|
+
cluster
|
|
434
|
+
.analytics_query(fmt::format(R"(SELECT testkey FROM `Default`.`{}` WHERE testkey = "{}")", dataset_name, test_value),
|
|
435
|
+
couchbase::analytics_options{}.scan_consistency(couchbase::analytics_scan_consistency::request_plus))
|
|
436
|
+
.get();
|
|
437
|
+
/* Analytics might give us code 23027, ignore it here
|
|
438
|
+
*
|
|
439
|
+
* "errors": [{"code": 23027, "msg": "Bucket default on link Default.Local is not connected"} ],
|
|
440
|
+
*/
|
|
441
|
+
return ctx.first_error_code() != 23027;
|
|
442
|
+
}));
|
|
443
|
+
|
|
444
|
+
REQUIRE_SUCCESS(ctx.ec());
|
|
445
|
+
auto rows = resp.rows_as_json();
|
|
446
|
+
REQUIRE(rows.size() == 1);
|
|
447
|
+
REQUIRE(rows[0] == document);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
SECTION("readonly")
|
|
451
|
+
{
|
|
452
|
+
auto [ctx, resp] =
|
|
453
|
+
cluster.analytics_query(fmt::format("DROP DATASET Default.`{}`", dataset_name), couchbase::analytics_options{}.readonly(true))
|
|
454
|
+
.get();
|
|
455
|
+
|
|
456
|
+
REQUIRE(ctx.ec() == couchbase::errc::common::internal_server_failure);
|
|
457
|
+
REQUIRE(resp.meta_data().status() == couchbase::analytics_status::fatal);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
{
|
|
461
|
+
couchbase::core::operations::management::analytics_dataset_drop_request req{};
|
|
462
|
+
req.dataset_name = dataset_name;
|
|
463
|
+
test::utils::execute(integration.cluster, req);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
TEST_CASE("integration: public API analytics scope query")
|
|
468
|
+
{
|
|
469
|
+
test::utils::integration_test_guard integration;
|
|
470
|
+
|
|
471
|
+
if (!integration.cluster_version().supports_analytics() || !integration.cluster_version().supports_collections()) {
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
auto cluster = couchbase::cluster(integration.cluster);
|
|
476
|
+
auto bucket = cluster.bucket(integration.ctx.bucket);
|
|
477
|
+
|
|
478
|
+
auto scope_name = test::utils::uniq_id("scope");
|
|
479
|
+
auto collection_name = test::utils::uniq_id("collection");
|
|
480
|
+
|
|
481
|
+
{
|
|
482
|
+
const couchbase::core::operations::management::scope_create_request req{ integration.ctx.bucket, scope_name };
|
|
483
|
+
auto resp = test::utils::execute(integration.cluster, req);
|
|
484
|
+
REQUIRE_SUCCESS(resp.ctx.ec);
|
|
485
|
+
auto created = test::utils::wait_until_collection_manifest_propagated(integration.cluster, integration.ctx.bucket, resp.uid);
|
|
486
|
+
REQUIRE(created);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
{
|
|
490
|
+
const couchbase::core::operations::management::collection_create_request req{ integration.ctx.bucket, scope_name, collection_name };
|
|
491
|
+
auto resp = test::utils::execute(integration.cluster, req);
|
|
492
|
+
REQUIRE_SUCCESS(resp.ctx.ec);
|
|
493
|
+
auto created = test::utils::wait_until_collection_manifest_propagated(integration.cluster, integration.ctx.bucket, resp.uid);
|
|
494
|
+
REQUIRE(created);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
CHECK(test::utils::wait_until(
|
|
498
|
+
[&]() {
|
|
499
|
+
auto [ctx, resp] = cluster
|
|
500
|
+
.analytics_query(fmt::format(
|
|
501
|
+
"ALTER COLLECTION `{}`.`{}`.`{}` ENABLE ANALYTICS", integration.ctx.bucket, scope_name, collection_name))
|
|
502
|
+
.get();
|
|
503
|
+
return !ctx.ec();
|
|
504
|
+
},
|
|
505
|
+
std::chrono::minutes{ 5 }));
|
|
506
|
+
|
|
507
|
+
auto scope = bucket.scope(scope_name);
|
|
508
|
+
auto collection = scope.collection(collection_name);
|
|
509
|
+
|
|
510
|
+
auto key = test::utils::uniq_id("key");
|
|
511
|
+
auto test_value = test::utils::uniq_id("value");
|
|
512
|
+
const tao::json::value document = {
|
|
513
|
+
{ "testkey", test_value },
|
|
514
|
+
};
|
|
515
|
+
{
|
|
516
|
+
auto [ctx, resp] = collection.upsert(key, document).get();
|
|
517
|
+
REQUIRE_SUCCESS(ctx.ec());
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
couchbase::analytics_result resp{};
|
|
521
|
+
couchbase::analytics_error_context ctx{};
|
|
522
|
+
CHECK(test::utils::wait_until([&]() {
|
|
523
|
+
std::tie(ctx, resp) =
|
|
524
|
+
scope.analytics_query(fmt::format(R"(SELECT testkey FROM `{}` WHERE testkey = "{}")", collection_name, test_value)).get();
|
|
525
|
+
return !ctx.ec() && resp.meta_data().metrics().result_count() == 1;
|
|
526
|
+
}));
|
|
527
|
+
REQUIRE_SUCCESS(ctx.ec());
|
|
528
|
+
REQUIRE(resp.rows_as_json()[0] == document);
|
|
529
|
+
REQUIRE_FALSE(resp.meta_data().request_id().empty());
|
|
530
|
+
REQUIRE_FALSE(resp.meta_data().client_context_id().empty());
|
|
531
|
+
REQUIRE(resp.meta_data().status() == couchbase::analytics_status::success);
|
|
532
|
+
|
|
533
|
+
{
|
|
534
|
+
const couchbase::core::operations::management::scope_drop_request req{ integration.ctx.bucket, scope_name };
|
|
535
|
+
test::utils::execute(integration.cluster, req);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
@@ -228,6 +228,9 @@ TEST_CASE("integration: pessimistic locking", "[integration]")
|
|
|
228
228
|
{
|
|
229
229
|
couchbase::core::operations::get_and_lock_request req{ id };
|
|
230
230
|
req.lock_time = lock_time;
|
|
231
|
+
if (integration.ctx.deployment == test::utils::deployment_type::capella) {
|
|
232
|
+
req.timeout = std::chrono::seconds{ 2 };
|
|
233
|
+
}
|
|
231
234
|
auto resp = test::utils::execute(integration.cluster, req);
|
|
232
235
|
REQUIRE(resp.ctx.ec() == couchbase::errc::common::ambiguous_timeout);
|
|
233
236
|
REQUIRE(resp.ctx.retried_because_of(couchbase::retry_reason::key_value_locked));
|
|
@@ -810,7 +813,11 @@ TEST_CASE("integration: pessimistic locking with public API", "[integration]")
|
|
|
810
813
|
|
|
811
814
|
// it is not allowed to lock the same key twice
|
|
812
815
|
{
|
|
813
|
-
|
|
816
|
+
couchbase::get_and_lock_options options{};
|
|
817
|
+
if (integration.ctx.deployment == test::utils::deployment_type::capella) {
|
|
818
|
+
options.timeout(std::chrono::seconds{ 2 });
|
|
819
|
+
}
|
|
820
|
+
auto [ctx, resp] = collection.get_and_lock(id, lock_time, options).get();
|
|
814
821
|
REQUIRE(ctx.ec() == couchbase::errc::common::ambiguous_timeout);
|
|
815
822
|
REQUIRE(ctx.retried_because_of(couchbase::retry_reason::key_value_locked));
|
|
816
823
|
}
|