couchbase 3.0.0.alpha.3 → 3.0.0.alpha.4
Sign up to get free protection for your applications and to get access to all the features.
- 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,102 @@
|
|
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
|
+
#include <version.hxx>
|
23
|
+
|
24
|
+
namespace couchbase::operations
|
25
|
+
{
|
26
|
+
struct analytics_link_connect_response {
|
27
|
+
struct problem {
|
28
|
+
std::uint32_t code;
|
29
|
+
std::string message;
|
30
|
+
};
|
31
|
+
|
32
|
+
std::string client_context_id;
|
33
|
+
std::error_code ec;
|
34
|
+
std::string status{};
|
35
|
+
std::vector<problem> errors{};
|
36
|
+
};
|
37
|
+
|
38
|
+
struct analytics_link_connect_request {
|
39
|
+
using response_type = analytics_link_connect_response;
|
40
|
+
using encoded_request_type = io::http_request;
|
41
|
+
using encoded_response_type = io::http_response;
|
42
|
+
|
43
|
+
static const inline service_type type = service_type::analytics;
|
44
|
+
|
45
|
+
std::string client_context_id{ uuid::to_string(uuid::random()) };
|
46
|
+
std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
|
47
|
+
|
48
|
+
std::string dataverse_name{ "Default" };
|
49
|
+
std::string link_name;
|
50
|
+
bool force{ false };
|
51
|
+
|
52
|
+
void encode_to(encoded_request_type& encoded)
|
53
|
+
{
|
54
|
+
std::string with_clause = force ? "WITH {\"force\": true}" : "";
|
55
|
+
|
56
|
+
tao::json::value body{
|
57
|
+
{ "statement", fmt::format("CONNECT LINK `{}`.`{}` {}", dataverse_name, link_name, with_clause) },
|
58
|
+
};
|
59
|
+
encoded.headers["content-type"] = "application/json";
|
60
|
+
encoded.method = "POST";
|
61
|
+
encoded.path = "/analytics/service";
|
62
|
+
encoded.body = tao::json::to_string(body);
|
63
|
+
}
|
64
|
+
};
|
65
|
+
|
66
|
+
analytics_link_connect_response
|
67
|
+
make_response(std::error_code ec, analytics_link_connect_request& request, analytics_link_connect_request::encoded_response_type encoded)
|
68
|
+
{
|
69
|
+
analytics_link_connect_response response{ request.client_context_id, ec };
|
70
|
+
if (!ec) {
|
71
|
+
auto payload = tao::json::from_string(encoded.body);
|
72
|
+
response.status = payload.at("status").get_string();
|
73
|
+
|
74
|
+
if (response.status != "success") {
|
75
|
+
bool link_not_found = false;
|
76
|
+
|
77
|
+
auto* errors = payload.find("errors");
|
78
|
+
if (errors != nullptr && errors->is_array()) {
|
79
|
+
for (const auto& error : errors->get_array()) {
|
80
|
+
analytics_link_connect_response::problem err{
|
81
|
+
error.at("code").as<std::uint32_t>(),
|
82
|
+
error.at("msg").get_string(),
|
83
|
+
};
|
84
|
+
switch (err.code) {
|
85
|
+
case 24006: /* Link [string] does not exist */
|
86
|
+
link_not_found = true;
|
87
|
+
break;
|
88
|
+
}
|
89
|
+
response.errors.emplace_back(err);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
if (link_not_found) {
|
93
|
+
response.ec = std::make_error_code(error::analytics_errc::link_not_found);
|
94
|
+
} else {
|
95
|
+
response.ec = std::make_error_code(error::common_errc::internal_server_failure);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
return response;
|
100
|
+
}
|
101
|
+
|
102
|
+
} // namespace couchbase::operations
|
@@ -0,0 +1,101 @@
|
|
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
|
+
#include <version.hxx>
|
23
|
+
|
24
|
+
namespace couchbase::operations
|
25
|
+
{
|
26
|
+
struct analytics_link_disconnect_response {
|
27
|
+
struct problem {
|
28
|
+
std::uint32_t code;
|
29
|
+
std::string message;
|
30
|
+
};
|
31
|
+
|
32
|
+
std::string client_context_id;
|
33
|
+
std::error_code ec;
|
34
|
+
std::string status{};
|
35
|
+
std::vector<problem> errors{};
|
36
|
+
};
|
37
|
+
|
38
|
+
struct analytics_link_disconnect_request {
|
39
|
+
using response_type = analytics_link_disconnect_response;
|
40
|
+
using encoded_request_type = io::http_request;
|
41
|
+
using encoded_response_type = io::http_response;
|
42
|
+
|
43
|
+
static const inline service_type type = service_type::analytics;
|
44
|
+
|
45
|
+
std::string client_context_id{ uuid::to_string(uuid::random()) };
|
46
|
+
std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
|
47
|
+
|
48
|
+
std::string dataverse_name{ "Default" };
|
49
|
+
std::string link_name;
|
50
|
+
|
51
|
+
void encode_to(encoded_request_type& encoded)
|
52
|
+
{
|
53
|
+
tao::json::value body{
|
54
|
+
{ "statement", fmt::format("DISCONNECT LINK `{}`.`{}`", dataverse_name, link_name) },
|
55
|
+
};
|
56
|
+
encoded.headers["content-type"] = "application/json";
|
57
|
+
encoded.method = "POST";
|
58
|
+
encoded.path = "/analytics/service";
|
59
|
+
encoded.body = tao::json::to_string(body);
|
60
|
+
}
|
61
|
+
};
|
62
|
+
|
63
|
+
analytics_link_disconnect_response
|
64
|
+
make_response(std::error_code ec,
|
65
|
+
analytics_link_disconnect_request& request,
|
66
|
+
analytics_link_disconnect_request::encoded_response_type encoded)
|
67
|
+
{
|
68
|
+
analytics_link_disconnect_response response{ request.client_context_id, ec };
|
69
|
+
if (!ec) {
|
70
|
+
auto payload = tao::json::from_string(encoded.body);
|
71
|
+
response.status = payload.at("status").get_string();
|
72
|
+
|
73
|
+
if (response.status != "success") {
|
74
|
+
bool link_not_found = false;
|
75
|
+
|
76
|
+
auto* errors = payload.find("errors");
|
77
|
+
if (errors != nullptr && errors->is_array()) {
|
78
|
+
for (const auto& error : errors->get_array()) {
|
79
|
+
analytics_link_disconnect_response::problem err{
|
80
|
+
error.at("code").as<std::uint32_t>(),
|
81
|
+
error.at("msg").get_string(),
|
82
|
+
};
|
83
|
+
switch (err.code) {
|
84
|
+
case 24006: /* Link [string] does not exist */
|
85
|
+
link_not_found = true;
|
86
|
+
break;
|
87
|
+
}
|
88
|
+
response.errors.emplace_back(err);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
if (link_not_found) {
|
92
|
+
response.ec = std::make_error_code(error::analytics_errc::link_not_found);
|
93
|
+
} else {
|
94
|
+
response.ec = std::make_error_code(error::common_errc::internal_server_failure);
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
98
|
+
return response;
|
99
|
+
}
|
100
|
+
|
101
|
+
} // namespace couchbase::operations
|
@@ -0,0 +1,59 @@
|
|
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
|
+
namespace couchbase::operations
|
21
|
+
{
|
22
|
+
struct design_document {
|
23
|
+
enum class name_space {
|
24
|
+
development,
|
25
|
+
production,
|
26
|
+
};
|
27
|
+
|
28
|
+
struct view {
|
29
|
+
std::string name;
|
30
|
+
std::optional<std::string> map;
|
31
|
+
std::optional<std::string> reduce;
|
32
|
+
};
|
33
|
+
|
34
|
+
std::string rev;
|
35
|
+
std::string name;
|
36
|
+
design_document::name_space ns;
|
37
|
+
std::map<std::string, view> views;
|
38
|
+
};
|
39
|
+
|
40
|
+
} // namespace couchbase::operations
|
41
|
+
|
42
|
+
template<>
|
43
|
+
struct fmt::formatter<couchbase::operations::design_document::name_space> : formatter<string_view> {
|
44
|
+
template<typename FormatContext>
|
45
|
+
auto format(couchbase::operations::design_document::name_space ns, FormatContext& ctx)
|
46
|
+
{
|
47
|
+
string_view name = "unknown";
|
48
|
+
switch (ns) {
|
49
|
+
case couchbase::operations::design_document::name_space::development:
|
50
|
+
name = "development";
|
51
|
+
break;
|
52
|
+
|
53
|
+
case couchbase::operations::design_document::name_space::production:
|
54
|
+
name = "production";
|
55
|
+
break;
|
56
|
+
}
|
57
|
+
return formatter<string_view>::format(name, ctx);
|
58
|
+
}
|
59
|
+
};
|
@@ -0,0 +1,293 @@
|
|
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 <gsl/gsl>
|
21
|
+
|
22
|
+
#include <spdlog/spdlog.h>
|
23
|
+
|
24
|
+
#include <tao/json.hpp>
|
25
|
+
|
26
|
+
#include <version.hxx>
|
27
|
+
|
28
|
+
#include <errors.hxx>
|
29
|
+
#include <mutation_token.hxx>
|
30
|
+
#include <service_type.hxx>
|
31
|
+
#include <platform/uuid.h>
|
32
|
+
#include <timeout_defaults.hxx>
|
33
|
+
#include <io/http_message.hxx>
|
34
|
+
|
35
|
+
namespace couchbase::operations
|
36
|
+
{
|
37
|
+
struct analytics_response_payload {
|
38
|
+
struct analytics_metrics {
|
39
|
+
std::string elapsed_time;
|
40
|
+
std::string execution_time;
|
41
|
+
std::uint64_t result_count;
|
42
|
+
std::uint64_t result_size;
|
43
|
+
std::optional<std::uint64_t> sort_count;
|
44
|
+
std::optional<std::uint64_t> mutation_count;
|
45
|
+
std::optional<std::uint64_t> error_count;
|
46
|
+
std::optional<std::uint64_t> warning_count;
|
47
|
+
};
|
48
|
+
|
49
|
+
struct analytics_problem {
|
50
|
+
std::uint64_t code;
|
51
|
+
std::string message;
|
52
|
+
};
|
53
|
+
|
54
|
+
struct analytics_meta_data {
|
55
|
+
std::string request_id;
|
56
|
+
std::string client_context_id;
|
57
|
+
std::string status;
|
58
|
+
analytics_metrics metrics;
|
59
|
+
std::optional<std::string> signature;
|
60
|
+
std::optional<std::string> profile;
|
61
|
+
std::optional<std::vector<analytics_problem>> warnings;
|
62
|
+
std::optional<std::vector<analytics_problem>> errors;
|
63
|
+
};
|
64
|
+
|
65
|
+
analytics_meta_data meta_data{};
|
66
|
+
std::vector<std::string> rows{};
|
67
|
+
};
|
68
|
+
} // namespace couchbase::operations
|
69
|
+
|
70
|
+
namespace tao::json
|
71
|
+
{
|
72
|
+
template<>
|
73
|
+
struct traits<couchbase::operations::analytics_response_payload> {
|
74
|
+
template<template<typename...> class Traits>
|
75
|
+
static couchbase::operations::analytics_response_payload as(const tao::json::basic_value<Traits>& v)
|
76
|
+
{
|
77
|
+
couchbase::operations::analytics_response_payload result;
|
78
|
+
result.meta_data.request_id = v.at("requestID").get_string();
|
79
|
+
result.meta_data.client_context_id = v.at("clientContextID").get_string();
|
80
|
+
result.meta_data.status = v.at("status").get_string();
|
81
|
+
const auto s = v.find("signature");
|
82
|
+
if (s != nullptr) {
|
83
|
+
result.meta_data.signature = tao::json::to_string(*s);
|
84
|
+
}
|
85
|
+
|
86
|
+
const auto p = v.find("profile");
|
87
|
+
if (p != nullptr) {
|
88
|
+
result.meta_data.profile = tao::json::to_string(*p);
|
89
|
+
}
|
90
|
+
|
91
|
+
const auto m = v.find("metrics");
|
92
|
+
if (m != nullptr) {
|
93
|
+
result.meta_data.metrics.result_count = m->at("resultCount").get_unsigned();
|
94
|
+
result.meta_data.metrics.result_size = m->at("resultSize").get_unsigned();
|
95
|
+
result.meta_data.metrics.elapsed_time = m->at("elapsedTime").get_string();
|
96
|
+
result.meta_data.metrics.execution_time = m->at("executionTime").get_string();
|
97
|
+
result.meta_data.metrics.sort_count = m->template optional<std::uint64_t>("sortCount");
|
98
|
+
result.meta_data.metrics.mutation_count = m->template optional<std::uint64_t>("mutationCount");
|
99
|
+
result.meta_data.metrics.error_count = m->template optional<std::uint64_t>("errorCount");
|
100
|
+
result.meta_data.metrics.warning_count = m->template optional<std::uint64_t>("warningCount");
|
101
|
+
}
|
102
|
+
|
103
|
+
const auto e = v.find("errors");
|
104
|
+
if (e != nullptr) {
|
105
|
+
std::vector<couchbase::operations::analytics_response_payload::analytics_problem> problems{};
|
106
|
+
for (auto& err : e->get_array()) {
|
107
|
+
couchbase::operations::analytics_response_payload::analytics_problem problem;
|
108
|
+
problem.code = err.at("code").get_unsigned();
|
109
|
+
problem.message = err.at("msg").get_string();
|
110
|
+
problems.emplace_back(problem);
|
111
|
+
}
|
112
|
+
result.meta_data.errors.emplace(problems);
|
113
|
+
}
|
114
|
+
|
115
|
+
const auto w = v.find("warnings");
|
116
|
+
if (w != nullptr) {
|
117
|
+
std::vector<couchbase::operations::analytics_response_payload::analytics_problem> problems{};
|
118
|
+
for (auto& warn : w->get_array()) {
|
119
|
+
couchbase::operations::analytics_response_payload::analytics_problem problem;
|
120
|
+
problem.code = warn.at("code").get_unsigned();
|
121
|
+
problem.message = warn.at("msg").get_string();
|
122
|
+
problems.emplace_back(problem);
|
123
|
+
}
|
124
|
+
result.meta_data.warnings.emplace(problems);
|
125
|
+
}
|
126
|
+
const auto r = v.find("results");
|
127
|
+
if (r != nullptr) {
|
128
|
+
result.rows.reserve(result.meta_data.metrics.result_count);
|
129
|
+
for (auto& row : r->get_array()) {
|
130
|
+
result.rows.emplace_back(tao::json::to_string(row));
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
return result;
|
135
|
+
}
|
136
|
+
};
|
137
|
+
} // namespace tao::json
|
138
|
+
|
139
|
+
namespace couchbase::operations
|
140
|
+
{
|
141
|
+
struct analytics_response {
|
142
|
+
std::string client_context_id;
|
143
|
+
std::error_code ec;
|
144
|
+
analytics_response_payload payload{};
|
145
|
+
};
|
146
|
+
|
147
|
+
struct analytics_request {
|
148
|
+
using response_type = analytics_response;
|
149
|
+
using encoded_request_type = io::http_request;
|
150
|
+
using encoded_response_type = io::http_response;
|
151
|
+
|
152
|
+
enum class scan_consistency_type { not_bounded, request_plus };
|
153
|
+
|
154
|
+
static const inline service_type type = service_type::analytics;
|
155
|
+
|
156
|
+
std::chrono::milliseconds timeout{ timeout_defaults::analytics_timeout };
|
157
|
+
std::string statement;
|
158
|
+
std::string client_context_id{ uuid::to_string(uuid::random()) };
|
159
|
+
|
160
|
+
bool readonly{ false };
|
161
|
+
bool priority{ false };
|
162
|
+
|
163
|
+
std::optional<scan_consistency_type> scan_consistency{};
|
164
|
+
std::optional<std::uint64_t> scan_wait{};
|
165
|
+
|
166
|
+
std::map<std::string, tao::json::value> raw{};
|
167
|
+
std::vector<tao::json::value> positional_parameters{};
|
168
|
+
std::map<std::string, tao::json::value> named_parameters{};
|
169
|
+
|
170
|
+
void encode_to(encoded_request_type& encoded)
|
171
|
+
{
|
172
|
+
encoded.headers["content-type"] = "application/json";
|
173
|
+
if (priority) {
|
174
|
+
encoded.headers["analytics-priority"] = "-1";
|
175
|
+
}
|
176
|
+
tao::json::value body{ { "statement", statement },
|
177
|
+
{ "client_context_id", client_context_id },
|
178
|
+
{ "timeout", fmt::format("{}ms", timeout.count()) } };
|
179
|
+
if (positional_parameters.empty()) {
|
180
|
+
for (auto& param : named_parameters) {
|
181
|
+
Expects(param.first.empty() == false);
|
182
|
+
std::string key = param.first;
|
183
|
+
if (key[0] != '$') {
|
184
|
+
key.insert(key.begin(), '$');
|
185
|
+
}
|
186
|
+
body[key] = param.second;
|
187
|
+
}
|
188
|
+
} else {
|
189
|
+
body["args"] = positional_parameters;
|
190
|
+
}
|
191
|
+
if (readonly) {
|
192
|
+
body["readonly"] = true;
|
193
|
+
}
|
194
|
+
if (scan_consistency) {
|
195
|
+
switch (scan_consistency.value()) {
|
196
|
+
case scan_consistency_type::not_bounded:
|
197
|
+
body["scan_consistency"] = "not_bounded";
|
198
|
+
break;
|
199
|
+
case scan_consistency_type::request_plus:
|
200
|
+
body["scan_consistency"] = "request_plus";
|
201
|
+
break;
|
202
|
+
}
|
203
|
+
if (scan_wait) {
|
204
|
+
body["scan_wait"] = fmt::format("{}ms", scan_wait.value());
|
205
|
+
}
|
206
|
+
}
|
207
|
+
for (auto& param : raw) {
|
208
|
+
body[param.first] = param.second;
|
209
|
+
}
|
210
|
+
encoded.method = "POST";
|
211
|
+
encoded.path = "/query/service";
|
212
|
+
encoded.body = tao::json::to_string(body);
|
213
|
+
spdlog::trace("analytics request: {}", encoded.body);
|
214
|
+
}
|
215
|
+
};
|
216
|
+
|
217
|
+
analytics_response
|
218
|
+
make_response(std::error_code ec, analytics_request& request, analytics_request::encoded_response_type encoded)
|
219
|
+
{
|
220
|
+
analytics_response response{ request.client_context_id, ec };
|
221
|
+
if (!ec) {
|
222
|
+
spdlog::trace("analytics response: {}", encoded.body);
|
223
|
+
response.payload = tao::json::from_string(encoded.body).as<analytics_response_payload>();
|
224
|
+
Expects(response.payload.meta_data.client_context_id == request.client_context_id);
|
225
|
+
if (response.payload.meta_data.status != "success") {
|
226
|
+
bool server_timeout = false;
|
227
|
+
bool job_queue_is_full = false;
|
228
|
+
bool dataset_not_found = false;
|
229
|
+
bool dataverse_not_found = false;
|
230
|
+
bool dataset_exists = false;
|
231
|
+
bool dataverse_exists = false;
|
232
|
+
bool link_not_found = false;
|
233
|
+
bool compilation_failure = false;
|
234
|
+
|
235
|
+
if (response.payload.meta_data.errors) {
|
236
|
+
for (const auto& error : *response.payload.meta_data.errors) {
|
237
|
+
switch (error.code) {
|
238
|
+
case 21002: /* Request timed out and will be cancelled */
|
239
|
+
server_timeout = true;
|
240
|
+
break;
|
241
|
+
case 23007: /* Job queue is full with [string] jobs */
|
242
|
+
job_queue_is_full = true;
|
243
|
+
break;
|
244
|
+
case 24044: /* Cannot find dataset [string] because there is no dataverse declared, nor an alias with name [string]!
|
245
|
+
*/
|
246
|
+
case 24045: /* Cannot find dataset [string] in dataverse [string] nor an alias with name [string]! */
|
247
|
+
case 24025: /* Cannot find dataset with name [string] in dataverse [string] */
|
248
|
+
dataset_not_found = true;
|
249
|
+
break;
|
250
|
+
case 24034: /* Cannot find dataverse with name [string] */
|
251
|
+
dataverse_not_found = true;
|
252
|
+
break;
|
253
|
+
case 24040: /* A dataset with name [string] already exists in dataverse [string] */
|
254
|
+
dataset_exists = true;
|
255
|
+
break;
|
256
|
+
case 24039: /* A dataverse with this name [string] already exists. */
|
257
|
+
dataverse_exists = true;
|
258
|
+
break;
|
259
|
+
case 24006: /* Link [string] does not exist | Link [string] does not exist */
|
260
|
+
link_not_found = true;
|
261
|
+
break;
|
262
|
+
default:
|
263
|
+
if (error.code >= 24000 && error.code < 25000) {
|
264
|
+
compilation_failure = true;
|
265
|
+
}
|
266
|
+
}
|
267
|
+
}
|
268
|
+
}
|
269
|
+
if (compilation_failure) {
|
270
|
+
response.ec = std::make_error_code(error::analytics_errc::compilation_failure);
|
271
|
+
} else if (link_not_found) {
|
272
|
+
response.ec = std::make_error_code(error::analytics_errc::link_not_found);
|
273
|
+
} else if (dataset_not_found) {
|
274
|
+
response.ec = std::make_error_code(error::analytics_errc::dataset_not_found);
|
275
|
+
} else if (dataverse_not_found) {
|
276
|
+
response.ec = std::make_error_code(error::analytics_errc::dataverse_not_found);
|
277
|
+
} else if (server_timeout) {
|
278
|
+
response.ec = std::make_error_code(error::common_errc::unambiguous_timeout);
|
279
|
+
} else if (dataset_exists) {
|
280
|
+
response.ec = std::make_error_code(error::analytics_errc::dataset_exists);
|
281
|
+
} else if (dataverse_exists) {
|
282
|
+
response.ec = std::make_error_code(error::analytics_errc::dataverse_exists);
|
283
|
+
} else if (job_queue_is_full) {
|
284
|
+
response.ec = std::make_error_code(error::analytics_errc::job_queue_full);
|
285
|
+
} else {
|
286
|
+
response.ec = std::make_error_code(error::common_errc::internal_server_failure);
|
287
|
+
}
|
288
|
+
}
|
289
|
+
}
|
290
|
+
return response;
|
291
|
+
}
|
292
|
+
|
293
|
+
} // namespace couchbase::operations
|