couchbase 3.0.0.alpha.3-universal-darwin-19 → 3.0.0.alpha.4-universal-darwin-19
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/.github/workflows/tests-6.0.3.yml +4 -1
- data/.github/workflows/tests-dev-preview.yml +4 -1
- data/.github/workflows/tests.yml +4 -1
- data/README.md +1 -1
- data/bin/check-cluster +31 -0
- data/bin/init-cluster +16 -4
- data/examples/analytics.rb +221 -0
- data/examples/managing_analytics_indexes.rb +72 -0
- data/examples/managing_view_indexes.rb +54 -0
- data/examples/search_with_consistency.rb +84 -0
- data/examples/view.rb +50 -0
- data/ext/.clang-tidy +1 -0
- data/ext/build_version.hxx.in +1 -1
- data/ext/couchbase/bucket.hxx +0 -1
- data/ext/couchbase/couchbase.cxx +1421 -55
- data/ext/couchbase/io/dns_client.hxx +215 -0
- data/ext/couchbase/io/dns_codec.hxx +207 -0
- data/ext/couchbase/io/dns_config.hxx +116 -0
- data/ext/couchbase/io/dns_message.hxx +558 -0
- data/ext/couchbase/io/http_session.hxx +16 -4
- data/ext/couchbase/io/mcbp_session.hxx +2 -1
- data/ext/couchbase/mutation_token.hxx +1 -1
- data/ext/couchbase/operations.hxx +19 -0
- data/ext/couchbase/operations/analytics_dataset_create.hxx +117 -0
- data/ext/couchbase/operations/analytics_dataset_drop.hxx +103 -0
- data/ext/couchbase/operations/analytics_dataset_get_all.hxx +107 -0
- data/ext/couchbase/operations/analytics_dataverse_create.hxx +104 -0
- data/ext/couchbase/operations/analytics_dataverse_drop.hxx +104 -0
- data/ext/couchbase/operations/analytics_get_pending_mutations.hxx +91 -0
- data/ext/couchbase/operations/analytics_index_create.hxx +128 -0
- data/ext/couchbase/operations/analytics_index_drop.hxx +110 -0
- data/ext/couchbase/operations/analytics_index_get_all.hxx +106 -0
- data/ext/couchbase/operations/analytics_link_connect.hxx +102 -0
- data/ext/couchbase/operations/analytics_link_disconnect.hxx +101 -0
- data/ext/couchbase/operations/design_document.hxx +59 -0
- data/ext/couchbase/operations/document_analytics.hxx +293 -0
- data/ext/couchbase/operations/document_query.hxx +2 -2
- data/ext/couchbase/operations/document_search.hxx +19 -1
- data/ext/couchbase/operations/document_view.hxx +227 -0
- data/ext/couchbase/operations/search_index.hxx +17 -0
- data/ext/couchbase/operations/search_index_control_ingest.hxx +3 -1
- data/ext/couchbase/operations/view_index_drop.hxx +67 -0
- data/ext/couchbase/operations/view_index_get.hxx +90 -0
- data/ext/couchbase/operations/view_index_get_all.hxx +125 -0
- data/ext/couchbase/operations/view_index_upsert.hxx +87 -0
- data/ext/couchbase/service_type.hxx +38 -1
- data/ext/couchbase/timeout_defaults.hxx +3 -1
- data/ext/couchbase/utils/connection_string.hxx +231 -0
- data/ext/couchbase/version.hxx +1 -1
- data/ext/test/main.cxx +3 -12
- data/lib/couchbase/analytics_options.rb +165 -0
- data/lib/couchbase/bucket.rb +49 -0
- data/lib/couchbase/cluster.rb +46 -207
- data/lib/couchbase/management/analytics_index_manager.rb +138 -24
- data/lib/couchbase/management/view_index_manager.rb +63 -10
- data/lib/couchbase/query_options.rb +219 -0
- data/lib/couchbase/search_options.rb +6 -6
- data/lib/couchbase/version.rb +1 -1
- data/lib/couchbase/view_options.rb +155 -0
- metadata +34 -2
@@ -0,0 +1,125 @@
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Copyright 2020 Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#pragma once
|
19
|
+
|
20
|
+
#include <tao/json.hpp>
|
21
|
+
#include <operations/design_document.hxx>
|
22
|
+
|
23
|
+
namespace couchbase::operations
|
24
|
+
{
|
25
|
+
struct view_index_get_all_response {
|
26
|
+
std::string client_context_id;
|
27
|
+
std::error_code ec;
|
28
|
+
std::vector<design_document> design_documents{};
|
29
|
+
};
|
30
|
+
|
31
|
+
struct view_index_get_all_request {
|
32
|
+
using response_type = view_index_get_all_response;
|
33
|
+
using encoded_request_type = io::http_request;
|
34
|
+
using encoded_response_type = io::http_response;
|
35
|
+
|
36
|
+
static const inline service_type type = service_type::management;
|
37
|
+
|
38
|
+
std::string client_context_id{ uuid::to_string(uuid::random()) };
|
39
|
+
std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
|
40
|
+
|
41
|
+
std::string bucket_name;
|
42
|
+
design_document::name_space name_space;
|
43
|
+
|
44
|
+
void encode_to(encoded_request_type& encoded)
|
45
|
+
{
|
46
|
+
encoded.method = "GET";
|
47
|
+
encoded.path = fmt::format("/pools/default/buckets/{}/ddocs", bucket_name);
|
48
|
+
}
|
49
|
+
};
|
50
|
+
|
51
|
+
view_index_get_all_response
|
52
|
+
make_response(std::error_code ec, view_index_get_all_request& request, view_index_get_all_request::encoded_response_type encoded)
|
53
|
+
{
|
54
|
+
view_index_get_all_response response{ request.client_context_id, ec };
|
55
|
+
if (!ec) {
|
56
|
+
if (encoded.status_code == 200) {
|
57
|
+
auto payload = tao::json::from_string(encoded.body);
|
58
|
+
auto* rows = payload.find("rows");
|
59
|
+
if (rows != nullptr && rows->is_array()) {
|
60
|
+
for (const auto& entry : rows->get_array()) {
|
61
|
+
const auto* dd = entry.find("doc");
|
62
|
+
if (dd == nullptr || !dd->is_object()) {
|
63
|
+
continue;
|
64
|
+
}
|
65
|
+
const auto* meta = dd->find("meta");
|
66
|
+
if (meta == nullptr || !meta->is_object()) {
|
67
|
+
continue;
|
68
|
+
}
|
69
|
+
|
70
|
+
design_document document{};
|
71
|
+
document.rev = meta->at("rev").get_string();
|
72
|
+
auto id = meta->at("id").get_string();
|
73
|
+
static const std::string prefix = "_design/";
|
74
|
+
if (id.find(prefix) == 0) {
|
75
|
+
document.name = id.substr(prefix.size());
|
76
|
+
} else {
|
77
|
+
document.name = id; // fall back, should not happen
|
78
|
+
}
|
79
|
+
static const std::string name_space_prefix = "dev_";
|
80
|
+
if (document.name.find(name_space_prefix) == 0) {
|
81
|
+
document.name = document.name.substr(name_space_prefix.size());
|
82
|
+
document.ns = couchbase::operations::design_document::name_space::development;
|
83
|
+
} else {
|
84
|
+
document.ns = couchbase::operations::design_document::name_space::production;
|
85
|
+
}
|
86
|
+
if (document.ns != request.name_space) {
|
87
|
+
continue;
|
88
|
+
}
|
89
|
+
|
90
|
+
const auto *json = dd->find("json");
|
91
|
+
if (json == nullptr || !json->is_object()) {
|
92
|
+
continue;
|
93
|
+
}
|
94
|
+
const auto* views = json->find("views");
|
95
|
+
if (views != nullptr && views->is_object()) {
|
96
|
+
for (const auto& view_entry : views->get_object()) {
|
97
|
+
couchbase::operations::design_document::view view;
|
98
|
+
view.name = view_entry.first;
|
99
|
+
if (view_entry.second.is_object()) {
|
100
|
+
const auto* map = view_entry.second.find("map");
|
101
|
+
if (map != nullptr && map->is_string()) {
|
102
|
+
view.map = map->get_string();
|
103
|
+
}
|
104
|
+
const auto* reduce = view_entry.second.find("reduce");
|
105
|
+
if (reduce != nullptr && reduce->is_string()) {
|
106
|
+
view.reduce = reduce->get_string();
|
107
|
+
}
|
108
|
+
}
|
109
|
+
document.views[view.name] = view;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
response.design_documents.emplace_back(document);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
} else if (encoded.status_code == 404) {
|
117
|
+
response.ec = std::make_error_code(error::common_errc::bucket_not_found);
|
118
|
+
} else {
|
119
|
+
response.ec = std::make_error_code(error::common_errc::internal_server_failure);
|
120
|
+
}
|
121
|
+
}
|
122
|
+
return response;
|
123
|
+
}
|
124
|
+
|
125
|
+
} // namespace couchbase::operations
|
@@ -0,0 +1,87 @@
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Copyright 2020 Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#pragma once
|
19
|
+
|
20
|
+
#include <tao/json.hpp>
|
21
|
+
|
22
|
+
namespace couchbase::operations
|
23
|
+
{
|
24
|
+
struct view_index_upsert_response {
|
25
|
+
std::string client_context_id;
|
26
|
+
std::error_code ec;
|
27
|
+
};
|
28
|
+
|
29
|
+
struct view_index_upsert_request {
|
30
|
+
using response_type = view_index_upsert_response;
|
31
|
+
using encoded_request_type = io::http_request;
|
32
|
+
using encoded_response_type = io::http_response;
|
33
|
+
|
34
|
+
static const inline service_type type = service_type::views;
|
35
|
+
|
36
|
+
std::string client_context_id{ uuid::to_string(uuid::random()) };
|
37
|
+
std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
|
38
|
+
|
39
|
+
std::string bucket_name;
|
40
|
+
design_document document;
|
41
|
+
|
42
|
+
void encode_to(encoded_request_type& encoded)
|
43
|
+
{
|
44
|
+
tao::json::value body;
|
45
|
+
body["views"] = tao::json::empty_object;
|
46
|
+
for (const auto& view : document.views) {
|
47
|
+
tao::json::value view_def;
|
48
|
+
if (view.second.map) {
|
49
|
+
view_def["map"] = *view.second.map;
|
50
|
+
}
|
51
|
+
if (view.second.reduce) {
|
52
|
+
view_def["reduce"] = *view.second.reduce;
|
53
|
+
}
|
54
|
+
body["views"][view.first] = view_def;
|
55
|
+
}
|
56
|
+
|
57
|
+
encoded.headers["content-type"] = "application/json";
|
58
|
+
encoded.method = "PUT";
|
59
|
+
encoded.path = fmt::format(
|
60
|
+
"/{}/_design/{}{}", bucket_name, document.ns == design_document::name_space::development ? "dev_" : "", document.name);
|
61
|
+
encoded.body = tao::json::to_string(body);
|
62
|
+
}
|
63
|
+
};
|
64
|
+
|
65
|
+
view_index_upsert_response
|
66
|
+
make_response(std::error_code ec, view_index_upsert_request& request, view_index_upsert_request::encoded_response_type encoded)
|
67
|
+
{
|
68
|
+
view_index_upsert_response response{ request.client_context_id, ec };
|
69
|
+
if (!ec) {
|
70
|
+
switch (encoded.status_code) {
|
71
|
+
case 200:
|
72
|
+
case 201:
|
73
|
+
break;
|
74
|
+
case 400:
|
75
|
+
response.ec = std::make_error_code(error::common_errc::invalid_argument);
|
76
|
+
break;
|
77
|
+
case 404:
|
78
|
+
response.ec = std::make_error_code(error::view_errc::design_document_not_found);
|
79
|
+
break;
|
80
|
+
default:
|
81
|
+
response.ec = std::make_error_code(error::common_errc::internal_server_failure);
|
82
|
+
}
|
83
|
+
}
|
84
|
+
return response;
|
85
|
+
}
|
86
|
+
|
87
|
+
} // namespace couchbase::operations
|
@@ -19,5 +19,42 @@
|
|
19
19
|
|
20
20
|
namespace couchbase
|
21
21
|
{
|
22
|
-
enum class service_type {
|
22
|
+
enum class service_type {
|
23
|
+
kv,
|
24
|
+
query,
|
25
|
+
analytics,
|
26
|
+
search,
|
27
|
+
views,
|
28
|
+
management,
|
29
|
+
};
|
23
30
|
}
|
31
|
+
|
32
|
+
template<>
|
33
|
+
struct fmt::formatter<couchbase::service_type> : formatter<std::string_view> {
|
34
|
+
template<typename FormatContext>
|
35
|
+
auto format(couchbase::service_type type, FormatContext& ctx)
|
36
|
+
{
|
37
|
+
string_view name = "unknown";
|
38
|
+
switch (type) {
|
39
|
+
case couchbase::service_type::kv:
|
40
|
+
name = "kv";
|
41
|
+
break;
|
42
|
+
case couchbase::service_type::query:
|
43
|
+
name = "query";
|
44
|
+
break;
|
45
|
+
case couchbase::service_type::analytics:
|
46
|
+
name = "analytics";
|
47
|
+
break;
|
48
|
+
case couchbase::service_type::search:
|
49
|
+
name = "search";
|
50
|
+
break;
|
51
|
+
case couchbase::service_type::views:
|
52
|
+
name = "views";
|
53
|
+
break;
|
54
|
+
case couchbase::service_type::management:
|
55
|
+
name = "management";
|
56
|
+
break;
|
57
|
+
}
|
58
|
+
return formatter<string_view>::format(name, ctx);
|
59
|
+
}
|
60
|
+
};
|
@@ -29,4 +29,6 @@ constexpr std::chrono::milliseconds query_timeout{ 75'000 };
|
|
29
29
|
constexpr std::chrono::milliseconds analytics_timeout{ 75'000 };
|
30
30
|
constexpr std::chrono::milliseconds search_timeout{ 75'000 };
|
31
31
|
constexpr std::chrono::milliseconds management_timeout{ 75'000 };
|
32
|
-
|
32
|
+
|
33
|
+
constexpr std::chrono::milliseconds dns_srv_timeout{ 500 };
|
34
|
+
} // namespace couchbase::timeout_defaults
|
@@ -0,0 +1,231 @@
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Copyright 2020 Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#pragma once
|
19
|
+
|
20
|
+
#include <string>
|
21
|
+
|
22
|
+
#include <tao/json/external/pegtl.hpp>
|
23
|
+
#include <tao/json/external/pegtl/contrib/uri.hpp>
|
24
|
+
|
25
|
+
namespace couchbase::utils
|
26
|
+
{
|
27
|
+
|
28
|
+
struct connection_string {
|
29
|
+
enum class bootstrap_mode {
|
30
|
+
unspecified,
|
31
|
+
gcccp,
|
32
|
+
http,
|
33
|
+
};
|
34
|
+
|
35
|
+
enum class address_type {
|
36
|
+
ipv4,
|
37
|
+
ipv6,
|
38
|
+
dns,
|
39
|
+
};
|
40
|
+
|
41
|
+
struct node {
|
42
|
+
std::string address;
|
43
|
+
std::uint16_t port;
|
44
|
+
address_type type;
|
45
|
+
bootstrap_mode mode{ bootstrap_mode::unspecified };
|
46
|
+
};
|
47
|
+
|
48
|
+
std::string scheme{};
|
49
|
+
bool tls{ false };
|
50
|
+
std::map<std::string, std::string> params{};
|
51
|
+
std::vector<node> bootstrap_nodes{};
|
52
|
+
|
53
|
+
std::optional<std::string> default_bucket_name{};
|
54
|
+
bootstrap_mode default_mode{ bootstrap_mode::unspecified };
|
55
|
+
std::uint16_t default_port{ 0 };
|
56
|
+
|
57
|
+
std::optional<std::string> error{};
|
58
|
+
};
|
59
|
+
|
60
|
+
namespace priv
|
61
|
+
{
|
62
|
+
using namespace tao::json::pegtl;
|
63
|
+
|
64
|
+
struct bucket_name : seq<uri::segment_nz> {
|
65
|
+
};
|
66
|
+
using param_key = star<sor<abnf::ALPHA, abnf::DIGIT, one<'_'>>>;
|
67
|
+
using param_value = star<sor<minus<uri::pchar, one<'=', '&', '?'>>, one<'/'>>>;
|
68
|
+
struct param : seq<param_key, one<'='>, param_value> {
|
69
|
+
};
|
70
|
+
|
71
|
+
using sub_delims = minus<uri::sub_delims, one<',', '='>>; // host and mode separators
|
72
|
+
struct reg_name : star<sor<uri::unreserved, uri::pct_encoded, sub_delims>> {
|
73
|
+
};
|
74
|
+
struct host : sor<uri::IP_literal, uri::IPv4address, reg_name> {
|
75
|
+
};
|
76
|
+
|
77
|
+
struct mode : sor<istring<'c', 'c', 'c', 'p'>, istring<'g', 'c', 'c', 'c', 'p'>, istring<'h', 't', 't', 'p'>, istring<'m', 'c', 'd'>> {
|
78
|
+
};
|
79
|
+
using node = seq<host, opt<uri::colon, uri::port>, opt<one<'='>, mode>>;
|
80
|
+
|
81
|
+
using opt_bucket_name = opt_must<one<'/'>, bucket_name>;
|
82
|
+
using opt_params = opt_must<one<'?'>, list_must<param, one<'&'>>>;
|
83
|
+
using opt_nodes = seq<list_must<node, one<',', ';'>>, opt_bucket_name>;
|
84
|
+
|
85
|
+
using grammar = must<seq<uri::scheme, one<':'>, uri::dslash, opt_nodes, opt_params, eof>>;
|
86
|
+
|
87
|
+
template<typename Rule>
|
88
|
+
struct action {
|
89
|
+
};
|
90
|
+
|
91
|
+
template<>
|
92
|
+
struct action<uri::scheme> {
|
93
|
+
template<typename ActionInput>
|
94
|
+
static void apply(const ActionInput& in, connection_string& cs, connection_string::node& /* cur_node */)
|
95
|
+
{
|
96
|
+
cs.scheme = in.string();
|
97
|
+
if (cs.scheme == "couchbase") {
|
98
|
+
cs.default_port = 11210;
|
99
|
+
cs.default_mode = connection_string::bootstrap_mode::gcccp;
|
100
|
+
cs.tls = false;
|
101
|
+
} else if (cs.scheme == "couchbases") {
|
102
|
+
cs.default_port = 11207;
|
103
|
+
cs.default_mode = connection_string::bootstrap_mode::gcccp;
|
104
|
+
cs.tls = true;
|
105
|
+
} else if (cs.scheme == "http") {
|
106
|
+
cs.default_port = 8091;
|
107
|
+
cs.default_mode = connection_string::bootstrap_mode::http;
|
108
|
+
cs.tls = false;
|
109
|
+
} else if (cs.scheme == "https") {
|
110
|
+
cs.default_port = 18091;
|
111
|
+
cs.default_mode = connection_string::bootstrap_mode::http;
|
112
|
+
cs.tls = true;
|
113
|
+
}
|
114
|
+
}
|
115
|
+
};
|
116
|
+
|
117
|
+
template<>
|
118
|
+
struct action<param> {
|
119
|
+
template<typename ActionInput>
|
120
|
+
static void apply(const ActionInput& in, connection_string& cs, connection_string::node& /* cur_node */)
|
121
|
+
{
|
122
|
+
const auto& pair = in.string();
|
123
|
+
auto eq = pair.find('=');
|
124
|
+
std::string key = pair.substr(0, eq);
|
125
|
+
cs.params[key] = (eq == std::string::npos) ? "" : pair.substr(eq + 1);
|
126
|
+
}
|
127
|
+
};
|
128
|
+
|
129
|
+
template<>
|
130
|
+
struct action<reg_name> {
|
131
|
+
template<typename ActionInput>
|
132
|
+
static void apply(const ActionInput& in, connection_string& /* cs */, connection_string::node& cur_node)
|
133
|
+
{
|
134
|
+
cur_node.type = connection_string::address_type::dns;
|
135
|
+
cur_node.address = in.string_view();
|
136
|
+
}
|
137
|
+
};
|
138
|
+
|
139
|
+
template<>
|
140
|
+
struct action<uri::IPv4address> {
|
141
|
+
template<typename ActionInput>
|
142
|
+
static void apply(const ActionInput& in, connection_string& /* cs */, connection_string::node& cur_node)
|
143
|
+
{
|
144
|
+
cur_node.type = connection_string::address_type::ipv4;
|
145
|
+
cur_node.address = in.string_view();
|
146
|
+
}
|
147
|
+
};
|
148
|
+
|
149
|
+
template<>
|
150
|
+
struct action<uri::IPv6address> {
|
151
|
+
template<typename ActionInput>
|
152
|
+
static void apply(const ActionInput& in, connection_string& /* cs */, connection_string::node& cur_node)
|
153
|
+
{
|
154
|
+
cur_node.type = connection_string::address_type::ipv6;
|
155
|
+
cur_node.address = in.string_view();
|
156
|
+
}
|
157
|
+
};
|
158
|
+
|
159
|
+
template<>
|
160
|
+
struct action<node> {
|
161
|
+
template<typename ActionInput>
|
162
|
+
static void apply(const ActionInput& /* in */, connection_string& cs, connection_string::node& cur_node)
|
163
|
+
{
|
164
|
+
cs.bootstrap_nodes.push_back(cur_node);
|
165
|
+
cur_node = {};
|
166
|
+
}
|
167
|
+
};
|
168
|
+
|
169
|
+
template<>
|
170
|
+
struct action<uri::port> {
|
171
|
+
template<typename ActionInput>
|
172
|
+
static void apply(const ActionInput& in, connection_string& /* cs */, connection_string::node& cur_node)
|
173
|
+
{
|
174
|
+
cur_node.port = static_cast<std::uint16_t>(std::stoul(in.string()));
|
175
|
+
}
|
176
|
+
};
|
177
|
+
|
178
|
+
template<>
|
179
|
+
struct action<mode> {
|
180
|
+
template<typename ActionInput>
|
181
|
+
static void apply(const ActionInput& in, connection_string& /* cs */, connection_string::node& cur_node)
|
182
|
+
{
|
183
|
+
std::string mode = in.string();
|
184
|
+
std::transform(mode.begin(), mode.end(), mode.begin(), [](unsigned char c) { return std::tolower(c); });
|
185
|
+
if (mode == "mcd" || mode == "gcccp" || mode == "cccp") {
|
186
|
+
cur_node.mode = connection_string::bootstrap_mode::gcccp;
|
187
|
+
} else if (mode == "http") {
|
188
|
+
cur_node.mode = connection_string::bootstrap_mode::http;
|
189
|
+
}
|
190
|
+
}
|
191
|
+
};
|
192
|
+
|
193
|
+
template<>
|
194
|
+
struct action<bucket_name> {
|
195
|
+
template<typename ActionInput>
|
196
|
+
static void apply(const ActionInput& in, connection_string& cs, connection_string::node& /* cur_node */)
|
197
|
+
{
|
198
|
+
cs.default_bucket_name = in.string();
|
199
|
+
}
|
200
|
+
};
|
201
|
+
} // namespace priv
|
202
|
+
|
203
|
+
static connection_string
|
204
|
+
parse_connection_string(const std::string& input)
|
205
|
+
{
|
206
|
+
connection_string res;
|
207
|
+
|
208
|
+
if (input.empty()) {
|
209
|
+
res.error = "failed to parse connection string: empty input";
|
210
|
+
return res;
|
211
|
+
}
|
212
|
+
|
213
|
+
auto in = tao::json::pegtl::memory_input(input, __FUNCTION__);
|
214
|
+
try {
|
215
|
+
connection_string::node node{};
|
216
|
+
tao::json::pegtl::parse<priv::grammar, priv::action>(in, res, node);
|
217
|
+
} catch (tao::json::pegtl::parse_error& e) {
|
218
|
+
for (const auto& position : e.positions) {
|
219
|
+
if (position.source == __FUNCTION__) {
|
220
|
+
res.error = fmt::format(
|
221
|
+
"failed to parse connection string (column: {}, trailer: \"{}\")", position.byte_in_line, input.substr(position.byte));
|
222
|
+
break;
|
223
|
+
}
|
224
|
+
}
|
225
|
+
if (!res.error) {
|
226
|
+
res.error = e.what();
|
227
|
+
}
|
228
|
+
}
|
229
|
+
return res;
|
230
|
+
}
|
231
|
+
} // namespace couchbase::utils
|