couchbase 4.2.1 → 4.2.2
Sign up to get free protection for your applications and to get access to all the features.
- package/CMakeLists.txt +1 -0
- package/deps/couchbase-cxx-client/.gitmodules +3 -0
- package/deps/couchbase-cxx-client/.idea/misc.xml +1 -0
- package/deps/couchbase-cxx-client/.idea/vcs.xml +1 -0
- package/deps/couchbase-cxx-client/CMakeLists.txt +11 -1
- package/deps/couchbase-cxx-client/README.md +3 -3
- package/deps/couchbase-cxx-client/cmake/CompilerWarnings.cmake +4 -1
- package/deps/couchbase-cxx-client/cmake/VersionInfo.cmake +13 -1
- package/deps/couchbase-cxx-client/cmake/build_version.hxx.in +1 -0
- package/deps/couchbase-cxx-client/core/cluster.hxx +15 -5
- package/deps/couchbase-cxx-client/core/impl/build_deferred_query_indexes.cxx +17 -6
- package/deps/couchbase-cxx-client/core/impl/cluster.cxx +1 -1
- package/deps/couchbase-cxx-client/core/impl/collection_query_index_manager.cxx +93 -0
- package/deps/couchbase-cxx-client/core/impl/configuration_profiles_registry.cxx +11 -0
- package/deps/couchbase-cxx-client/core/impl/create_query_index.cxx +119 -0
- package/deps/couchbase-cxx-client/core/impl/drop_query_index.cxx +108 -0
- package/deps/couchbase-cxx-client/core/impl/get.cxx +1 -1
- package/deps/couchbase-cxx-client/core/impl/get_all_query_indexes.cxx +76 -0
- package/deps/couchbase-cxx-client/core/impl/query.cxx +5 -7
- package/deps/couchbase-cxx-client/core/impl/watch_query_indexes.cxx +168 -0
- package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +15 -1
- package/deps/couchbase-cxx-client/core/logger/configuration.hxx +3 -0
- package/deps/couchbase-cxx-client/core/logger/level.hxx +21 -0
- package/deps/couchbase-cxx-client/core/logger/logger.hxx +4 -6
- package/deps/couchbase-cxx-client/core/meta/CMakeLists.txt +4 -2
- package/deps/couchbase-cxx-client/core/meta/features.hxx +31 -0
- package/deps/couchbase-cxx-client/core/meta/version.cxx +67 -5
- package/deps/couchbase-cxx-client/core/meta/version.hxx +12 -1
- package/deps/couchbase-cxx-client/core/metrics/CMakeLists.txt +4 -1
- package/deps/couchbase-cxx-client/core/metrics/logging_meter.cxx +46 -5
- package/deps/couchbase-cxx-client/core/metrics/logging_meter.hxx +10 -26
- package/deps/couchbase-cxx-client/core/operations/document_get_projected.cxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/document_query.cxx +10 -12
- package/deps/couchbase-cxx-client/core/operations/document_query.hxx +1 -3
- package/deps/couchbase-cxx-client/core/operations/management/query_index_build.cxx +8 -14
- package/deps/couchbase-cxx-client/core/operations/management/query_index_build.hxx +2 -1
- package/deps/couchbase-cxx-client/core/operations/management/query_index_build_deferred.hxx +15 -8
- package/deps/couchbase-cxx-client/core/operations/management/query_index_create.cxx +7 -14
- package/deps/couchbase-cxx-client/core/operations/management/query_index_create.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.cxx +11 -16
- package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.cxx +8 -12
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.hxx +4 -3
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.cxx +21 -12
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.hxx +3 -2
- package/deps/couchbase-cxx-client/core/origin.hxx +1 -1
- package/deps/couchbase-cxx-client/core/platform/uuid.cc +1 -2
- package/deps/couchbase-cxx-client/core/protocol/cmd_hello.hxx +5 -1
- package/deps/couchbase-cxx-client/core/query_context.hxx +79 -0
- package/deps/couchbase-cxx-client/core/tracing/CMakeLists.txt +3 -1
- package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.cxx +19 -4
- package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.hxx +2 -2
- package/deps/couchbase-cxx-client/core/transactions/async_attempt_context.hxx +10 -4
- package/deps/couchbase-cxx-client/core/transactions/atr_cleanup_entry.cxx +52 -63
- package/deps/couchbase-cxx-client/core/transactions/attempt_context.hxx +8 -3
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +163 -126
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.hxx +24 -37
- package/deps/couchbase-cxx-client/core/transactions/forward_compat.hxx +4 -4
- package/deps/couchbase-cxx-client/core/transactions/internal/atr_cleanup_entry.hxx +51 -13
- package/deps/couchbase-cxx-client/core/transactions/internal/client_record.hxx +26 -1
- package/deps/couchbase-cxx-client/core/transactions/internal/doc_record.hxx +21 -0
- package/deps/couchbase-cxx-client/core/transactions/internal/logging.hxx +40 -18
- package/deps/couchbase-cxx-client/core/transactions/internal/transaction_context.hxx +5 -0
- package/deps/couchbase-cxx-client/core/transactions/result.hxx +26 -0
- package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +48 -47
- package/deps/couchbase-cxx-client/core/transactions/staged_mutation.hxx +6 -6
- package/deps/couchbase-cxx-client/core/transactions/transaction_context.cxx +33 -19
- package/deps/couchbase-cxx-client/core/transactions/transaction_get_result.hxx +18 -2
- package/deps/couchbase-cxx-client/core/transactions/transaction_links.hxx +25 -2
- package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +4 -4
- package/deps/couchbase-cxx-client/core/transactions/transactions_cleanup.cxx +49 -56
- package/deps/couchbase-cxx-client/core/transactions/waitable_op_list.hxx +7 -7
- package/deps/couchbase-cxx-client/core/transactions.hxx +0 -12
- package/deps/couchbase-cxx-client/core/utils/binary.hxx +1 -1
- package/deps/couchbase-cxx-client/core/utils/keyspace.hxx +55 -0
- package/deps/couchbase-cxx-client/couchbase/build_query_index_options.hxx +12 -45
- package/deps/couchbase-cxx-client/couchbase/cluster.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/cluster_options.hxx +6 -7
- package/deps/couchbase-cxx-client/couchbase/collection.hxx +8 -0
- package/deps/couchbase-cxx-client/couchbase/collection_query_index_manager.hxx +218 -0
- package/deps/couchbase-cxx-client/couchbase/configuration_profiles_registry.hxx +3 -0
- package/deps/couchbase-cxx-client/couchbase/create_primary_query_index_options.hxx +166 -0
- package/deps/couchbase-cxx-client/couchbase/create_query_index_options.hxx +172 -0
- package/deps/couchbase-cxx-client/couchbase/drop_primary_query_index_options.hxx +129 -0
- package/deps/couchbase-cxx-client/couchbase/drop_query_index_options.hxx +116 -0
- package/deps/couchbase-cxx-client/couchbase/fmt/cas.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/fmt/query_scan_consistency.hxx +46 -0
- package/deps/couchbase-cxx-client/couchbase/fmt/query_status.hxx +70 -0
- package/deps/couchbase-cxx-client/couchbase/fmt/tls_verify_mode.hxx +46 -0
- package/deps/couchbase-cxx-client/couchbase/get_all_query_indexes_options.hxx +100 -0
- package/deps/couchbase-cxx-client/{core → couchbase}/management/query_index.hxx +2 -2
- package/deps/couchbase-cxx-client/couchbase/metrics/meter.hxx +16 -0
- package/deps/couchbase-cxx-client/couchbase/query_index_manager.hxx +178 -6
- package/deps/couchbase-cxx-client/couchbase/query_options.hxx +1 -18
- package/deps/couchbase-cxx-client/couchbase/scope.hxx +5 -2
- package/deps/couchbase-cxx-client/couchbase/tracing/request_tracer.hxx +16 -0
- package/deps/couchbase-cxx-client/couchbase/transactions/async_attempt_context.hxx +11 -4
- package/deps/couchbase-cxx-client/couchbase/transactions/attempt_context.hxx +5 -3
- package/deps/couchbase-cxx-client/couchbase/transactions/transaction_keyspace.hxx +16 -0
- package/deps/couchbase-cxx-client/couchbase/transactions/transaction_query_options.hxx +0 -6
- package/deps/couchbase-cxx-client/couchbase/watch_query_indexes_options.hxx +115 -0
- package/deps/couchbase-cxx-client/examples/minimal.cxx +3 -1
- package/deps/couchbase-cxx-client/test/test_integration_crud.cxx +72 -0
- package/deps/couchbase-cxx-client/test/test_integration_management.cxx +727 -310
- package/deps/couchbase-cxx-client/test/test_integration_query.cxx +4 -8
- package/deps/couchbase-cxx-client/test/test_integration_transcoders.cxx +14 -0
- package/deps/couchbase-cxx-client/test/test_transaction_transaction_public_blocking_api.cxx +34 -19
- package/deps/couchbase-cxx-client/test/test_unit_transaction_logging.cxx +66 -22
- package/deps/couchbase-cxx-client/test/test_unit_utils.cxx +51 -0
- package/deps/couchbase-cxx-client/test/tools/tool_kv_loader.cxx +2 -2
- package/deps/couchbase-cxx-client/test/utils/integration_test_guard.cxx +2 -0
- package/deps/couchbase-cxx-client/test/utils/wait_until.cxx +4 -4
- package/deps/couchbase-cxx-client/third_party/docopt/.travis.yml +103 -0
- package/deps/couchbase-cxx-client/third_party/docopt/CMakeLists.txt +129 -0
- package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-Boost-1.0 +23 -0
- package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-MIT +23 -0
- package/deps/couchbase-cxx-client/third_party/docopt/README.rst +479 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt-config.cmake +1 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt.cpp +687 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt.h +98 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt.pc.in +9 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt_private.h +676 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt_util.h +122 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt_value.h +341 -0
- package/deps/couchbase-cxx-client/third_party/docopt/examples/naval_fate.cpp +36 -0
- package/deps/couchbase-cxx-client/third_party/docopt/main.cpp +16 -0
- package/deps/couchbase-cxx-client/third_party/docopt/run_testcase.cpp +40 -0
- package/deps/couchbase-cxx-client/third_party/docopt/run_tests.py +72 -0
- package/deps/couchbase-cxx-client/third_party/docopt/testcases.docopt +957 -0
- package/deps/couchbase-cxx-client/tools/CMakeLists.txt +14 -0
- package/deps/couchbase-cxx-client/tools/cbc.cxx +65 -0
- package/deps/couchbase-cxx-client/tools/command.hxx +31 -0
- package/deps/couchbase-cxx-client/tools/command_registry.cxx +43 -0
- package/deps/couchbase-cxx-client/tools/command_registry.hxx +39 -0
- package/deps/couchbase-cxx-client/tools/get.cxx +267 -0
- package/deps/couchbase-cxx-client/tools/get.hxx +26 -0
- package/deps/couchbase-cxx-client/tools/query.cxx +441 -0
- package/deps/couchbase-cxx-client/tools/query.hxx +26 -0
- package/deps/couchbase-cxx-client/tools/utils.cxx +418 -0
- package/deps/couchbase-cxx-client/tools/utils.hxx +150 -0
- package/deps/couchbase-cxx-client/tools/version.cxx +82 -0
- package/deps/couchbase-cxx-client/tools/version.hxx +26 -0
- package/dist/authenticators.d.ts +2 -2
- package/dist/authenticators.js +1 -2
- package/dist/binding.d.ts +32 -16
- package/dist/cluster.js +14 -7
- package/dist/collection.d.ts +6 -0
- package/dist/collection.js +8 -0
- package/dist/queryexecutor.js +1 -1
- package/dist/queryindexmanager.d.ts +100 -4
- package/dist/queryindexmanager.js +344 -118
- package/dist/transactions.js +0 -2
- package/package.json +1 -1
- package/src/connection.cpp +2 -0
- package/src/connection.hpp +1 -0
- package/src/connection_autogen.cpp +16 -0
- package/src/jstocbpp_autogen.hpp +93 -23
- package/src/jstocbpp_basic.hpp +24 -0
- package/src/jstocbpp_transactions.hpp +0 -8
- package/tools/gen-bindings-js.js +1 -0
- package/tools/gen-bindings-json.py +4 -2
- package/deps/couchbase-cxx-client/core/transactions/logging.cxx +0 -107
@@ -0,0 +1,441 @@
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Copyright 2023-Present 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
|
+
#include "query.hxx"
|
19
|
+
#include "core/utils/binary.hxx"
|
20
|
+
#include "utils.hxx"
|
21
|
+
|
22
|
+
#include <core/logger/logger.hxx>
|
23
|
+
#include <couchbase/cluster.hxx>
|
24
|
+
#include <couchbase/fmt/query_status.hxx>
|
25
|
+
|
26
|
+
#include <asio/io_context.hpp>
|
27
|
+
#include <fmt/chrono.h>
|
28
|
+
#include <spdlog/fmt/bin_to_hex.h>
|
29
|
+
#include <tao/json.hpp>
|
30
|
+
|
31
|
+
#include <regex>
|
32
|
+
|
33
|
+
namespace cbc
|
34
|
+
{
|
35
|
+
namespace
|
36
|
+
{
|
37
|
+
static auto
|
38
|
+
usage() -> std::string
|
39
|
+
{
|
40
|
+
static const std::string default_bucket_name{ "default" };
|
41
|
+
|
42
|
+
static const std::string usage_string = fmt::format(
|
43
|
+
R"(Display version information.
|
44
|
+
|
45
|
+
Usage:
|
46
|
+
cbc query [options] <statement>...
|
47
|
+
cbc query [options] --param=NAME=VALUE... <statement>...
|
48
|
+
cbc query [options] --raw=NAME=VALUE... <statement>...
|
49
|
+
cbc query (-h|--help)
|
50
|
+
|
51
|
+
Options:
|
52
|
+
-h --help Show this screen.
|
53
|
+
--param=NAME=VALUE Parameters for the query. Without '=' sign value will be treated as positional parameter.
|
54
|
+
--prepare Prepare statement.
|
55
|
+
--read-only Mark query as read only. Any mutations will fail.
|
56
|
+
--preserve-expiry Ensure that expiry will be preserved after mutations.
|
57
|
+
--disable-metrics Do not request metrics.
|
58
|
+
--profile=MODE Request the service to profile the query and return report (allowed values: off, phases, timings).
|
59
|
+
--bucket-name=STRING Name of the bucket where the scope is defined (see --scope-name).
|
60
|
+
--scope-name=STRING Name of the scope.
|
61
|
+
--client-context-id=STRING Override client context ID for the query(-ies).
|
62
|
+
--flex-index Tell query service to utilize flex index (full text search).
|
63
|
+
--maximum-parallelism=INTEGER Parallelism for query execution (0 to disable).
|
64
|
+
--scan-cap=INTEGER Maximum buffer size between indexer and query service.
|
65
|
+
--scan-wait=DURATION How long query engine will wait for indexer to catch up on scan consistency.
|
66
|
+
--scan-consistency=MODE Set consistency guarantees for the query (allowed values: not_bounded, request_plus).
|
67
|
+
--pipeline-batch=INTEGER Number of items execution operators can batch for fetch from the Key/Value service.
|
68
|
+
--pipeline-cap=INTEGER Maximum number of items each execution operator can buffer between various operators.
|
69
|
+
--raw=NAME=VALUE Set any query option for the query. Read the documentation: https://docs.couchbase.com/server/current/n1ql/n1ql-rest-api.
|
70
|
+
--json-lines Use JSON Lines format (https://jsonlines.org/) to print results.
|
71
|
+
|
72
|
+
{logger_options}{cluster_options}
|
73
|
+
|
74
|
+
Examples:
|
75
|
+
|
76
|
+
1. Query with positional parameters:
|
77
|
+
|
78
|
+
cbc query --param 1 --param 2 'SELECT $1 + $2'
|
79
|
+
|
80
|
+
2. Query with named parameters:
|
81
|
+
|
82
|
+
cbc query --param a=1 --param b=2 'SELECT $a + $b'
|
83
|
+
)",
|
84
|
+
fmt::arg("logger_options", usage_block_for_logger()),
|
85
|
+
fmt::arg("cluster_options", usage_block_for_cluster_options()));
|
86
|
+
|
87
|
+
return usage_string;
|
88
|
+
}
|
89
|
+
|
90
|
+
struct console_output_options {
|
91
|
+
bool json_lines{ false };
|
92
|
+
};
|
93
|
+
|
94
|
+
struct scope_with_bucket {
|
95
|
+
std::string bucket_name;
|
96
|
+
std::string scope_name;
|
97
|
+
};
|
98
|
+
|
99
|
+
template<typename QueryEndpoint>
|
100
|
+
static auto
|
101
|
+
do_query(QueryEndpoint& endpoint, std::string statement, const couchbase::query_options& options)
|
102
|
+
{
|
103
|
+
return endpoint.query(std::move(statement), options);
|
104
|
+
}
|
105
|
+
|
106
|
+
static void
|
107
|
+
print_result_json_line(const std::optional<scope_with_bucket>& scope_id,
|
108
|
+
const std::string& statement,
|
109
|
+
const couchbase::query_error_context& ctx,
|
110
|
+
const couchbase::query_result& resp,
|
111
|
+
const couchbase::query_options& query_options)
|
112
|
+
{
|
113
|
+
auto built_options = query_options.build();
|
114
|
+
|
115
|
+
tao::json::value line = tao::json::empty_object;
|
116
|
+
|
117
|
+
tao::json::value meta = {
|
118
|
+
{ "statement", statement },
|
119
|
+
};
|
120
|
+
if (scope_id) {
|
121
|
+
meta["bucket_name"] = scope_id->bucket_name;
|
122
|
+
meta["scope_name"] = scope_id->scope_name;
|
123
|
+
}
|
124
|
+
if (ctx.parameters()) {
|
125
|
+
try {
|
126
|
+
auto json = tao::json::from_string(ctx.parameters().value());
|
127
|
+
json.erase("statement");
|
128
|
+
meta["options"] = json;
|
129
|
+
} catch (const tao::pegtl::parse_error&) {
|
130
|
+
meta["options"] = ctx.parameters().value();
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
if (ctx.ec()) {
|
135
|
+
tao::json::value error = {
|
136
|
+
{ "code", ctx.ec().value() },
|
137
|
+
{ "message", ctx.ec().message() },
|
138
|
+
};
|
139
|
+
try {
|
140
|
+
error["body"] = tao::json::from_string(ctx.http_body());
|
141
|
+
} catch (const tao::pegtl::parse_error&) {
|
142
|
+
error["text"] = ctx.http_body();
|
143
|
+
}
|
144
|
+
line["error"] = error;
|
145
|
+
} else {
|
146
|
+
meta["status"] = fmt::format("{}", resp.meta_data().status());
|
147
|
+
meta["client_context_id"] = resp.meta_data().client_context_id();
|
148
|
+
meta["request_id"] = resp.meta_data().request_id();
|
149
|
+
if (const auto& signature = resp.meta_data().signature()) {
|
150
|
+
try {
|
151
|
+
meta["signature"] = couchbase::core::utils::json::parse_binary(signature.value());
|
152
|
+
} catch (const tao::pegtl::parse_error&) {
|
153
|
+
meta["signature"] = signature.value();
|
154
|
+
}
|
155
|
+
}
|
156
|
+
if (const auto& metrics = resp.meta_data().metrics(); metrics.has_value()) {
|
157
|
+
meta["metrics"] = {
|
158
|
+
{ "elapsed_time", fmt::format("{}", metrics->elapsed_time()) },
|
159
|
+
{ "execution_time", fmt::format("{}", metrics->execution_time()) },
|
160
|
+
{ "result_count", metrics->result_count() },
|
161
|
+
{ "result_size", metrics->result_size() },
|
162
|
+
{ "sort_count", metrics->sort_count() },
|
163
|
+
{ "mutation_count", metrics->mutation_count() },
|
164
|
+
{ "error_count", metrics->error_count() },
|
165
|
+
{ "warning_count", metrics->warning_count() },
|
166
|
+
};
|
167
|
+
}
|
168
|
+
if (const auto& profile = resp.meta_data().profile(); profile) {
|
169
|
+
try {
|
170
|
+
meta["profile"] = couchbase::core::utils::json::parse_binary(profile.value());
|
171
|
+
} catch (const tao::pegtl::parse_error&) {
|
172
|
+
meta["profile"] = profile.value();
|
173
|
+
}
|
174
|
+
}
|
175
|
+
if (!resp.meta_data().warnings().empty()) {
|
176
|
+
tao::json::value warnings = tao::json::empty_array;
|
177
|
+
for (const auto& item : resp.meta_data().warnings()) {
|
178
|
+
tao::json::value warning = {
|
179
|
+
{ "message", item.message() },
|
180
|
+
{ "code", item.code() },
|
181
|
+
};
|
182
|
+
if (item.reason()) {
|
183
|
+
warning["reason"] = item.reason().value();
|
184
|
+
}
|
185
|
+
if (item.retry()) {
|
186
|
+
warning["retry"] = item.retry().value();
|
187
|
+
}
|
188
|
+
warnings.emplace_back(warning);
|
189
|
+
}
|
190
|
+
meta["warnings"] = warnings;
|
191
|
+
}
|
192
|
+
tao::json::value rows = tao::json::empty_array;
|
193
|
+
for (const auto& row : resp.rows_as_binary()) {
|
194
|
+
try {
|
195
|
+
rows.emplace_back(couchbase::core::utils::json::parse_binary(row));
|
196
|
+
} catch (const tao::pegtl::parse_error&) {
|
197
|
+
rows.emplace_back(row);
|
198
|
+
}
|
199
|
+
}
|
200
|
+
line["rows"] = rows;
|
201
|
+
}
|
202
|
+
line["meta"] = meta;
|
203
|
+
fmt::print(stdout, "{}\n", tao::json::to_string<tao::json::events::binary_to_base64>(line));
|
204
|
+
fflush(stdout);
|
205
|
+
}
|
206
|
+
|
207
|
+
static void
|
208
|
+
print_result(const std::optional<scope_with_bucket>& scope_id,
|
209
|
+
const std::string& statement,
|
210
|
+
const couchbase::query_error_context& ctx,
|
211
|
+
const couchbase::query_result& resp,
|
212
|
+
const couchbase::query_options& query_options)
|
213
|
+
{
|
214
|
+
auto built_options = query_options.build();
|
215
|
+
|
216
|
+
auto header = fmt::memory_buffer();
|
217
|
+
if (scope_id) {
|
218
|
+
fmt::format_to(std::back_inserter(header), "bucket_name: {}, scope_name: {}", scope_id->bucket_name, scope_id->scope_name);
|
219
|
+
}
|
220
|
+
fmt::format_to(
|
221
|
+
std::back_inserter(header), "{}statement: \"{}\"", header.size() == 0 ? "" : ", ", tao::json::internal::escape(statement));
|
222
|
+
|
223
|
+
if (ctx.parameters()) {
|
224
|
+
try {
|
225
|
+
auto json = tao::json::from_string(ctx.parameters().value());
|
226
|
+
json.erase("statement");
|
227
|
+
fmt::format_to(std::back_inserter(header), ", options: {}", tao::json::to_string(json));
|
228
|
+
} catch (const tao::pegtl::parse_error&) {
|
229
|
+
fmt::format_to(std::back_inserter(header), ", options: {}", ctx.parameters().value());
|
230
|
+
}
|
231
|
+
}
|
232
|
+
fmt::print(stdout, "--- {}\n", std::string_view{ header.data(), header.size() });
|
233
|
+
|
234
|
+
if (ctx.ec()) {
|
235
|
+
fmt::print("ERROR. code: {}, message: {}, server: {} \"{}\")\n",
|
236
|
+
ctx.ec().value(),
|
237
|
+
ctx.ec().message(),
|
238
|
+
ctx.first_error_code(),
|
239
|
+
tao::json::internal::escape(ctx.first_error_message()));
|
240
|
+
if (!ctx.http_body().empty()) {
|
241
|
+
try {
|
242
|
+
fmt::print("{}\n", tao::json::to_string(tao::json::from_string(ctx.http_body())));
|
243
|
+
} catch (const tao::pegtl::parse_error&) {
|
244
|
+
fmt::print("{}\n", ctx.http_body());
|
245
|
+
}
|
246
|
+
}
|
247
|
+
} else {
|
248
|
+
auto meta = fmt::memory_buffer();
|
249
|
+
fmt::format_to(std::back_inserter(meta),
|
250
|
+
"status: {}, client_context_id: \"{}\", request_id: \"{}\"",
|
251
|
+
resp.meta_data().status(),
|
252
|
+
resp.meta_data().client_context_id(),
|
253
|
+
resp.meta_data().request_id());
|
254
|
+
if (const auto& metrics = resp.meta_data().metrics(); metrics.has_value()) {
|
255
|
+
fmt::format_to(std::back_inserter(meta),
|
256
|
+
", elapsed: {}, execution: {}, result: {}, sort: {}, mutations: {}, errors: {}, warnings: {}",
|
257
|
+
metrics->elapsed_time(),
|
258
|
+
metrics->execution_time(),
|
259
|
+
metrics->result_count(),
|
260
|
+
metrics->sort_count(),
|
261
|
+
metrics->mutation_count(),
|
262
|
+
metrics->error_count(),
|
263
|
+
metrics->warning_count());
|
264
|
+
}
|
265
|
+
fmt::print(stdout, "{}\n", std::string_view{ meta.data(), meta.size() });
|
266
|
+
if (!resp.meta_data().warnings().empty()) {
|
267
|
+
for (const auto& item : resp.meta_data().warnings()) {
|
268
|
+
auto warning = fmt::memory_buffer();
|
269
|
+
fmt::format_to(std::back_inserter(warning), "WARNING. code: {}, message: \"{}\"\n", item.code(), item.message());
|
270
|
+
if (item.reason()) {
|
271
|
+
fmt::format_to(std::back_inserter(warning), ", reason: {}\n", item.reason().value());
|
272
|
+
}
|
273
|
+
if (item.retry()) {
|
274
|
+
fmt::format_to(std::back_inserter(warning), ", retry: {}\n", item.retry().value());
|
275
|
+
}
|
276
|
+
fmt::print(stdout, "{}\n", std::string_view{ warning.data(), warning.size() });
|
277
|
+
}
|
278
|
+
}
|
279
|
+
if (const auto& profile = resp.meta_data().profile(); profile) {
|
280
|
+
try {
|
281
|
+
fmt::print("{}\n", tao::json::to_string(couchbase::core::utils::json::parse_binary(profile.value()), 2));
|
282
|
+
} catch (const tao::pegtl::parse_error&) {
|
283
|
+
fmt::print("{:a}\n", spdlog::to_hex(profile.value()));
|
284
|
+
}
|
285
|
+
}
|
286
|
+
for (const auto& row : resp.rows_as_binary()) {
|
287
|
+
try {
|
288
|
+
fmt::print("{}\n", tao::json::to_string(couchbase::core::utils::json::parse_binary(row)));
|
289
|
+
} catch (const tao::pegtl::parse_error&) {
|
290
|
+
fmt::print("{:a}\n", spdlog::to_hex(row));
|
291
|
+
}
|
292
|
+
}
|
293
|
+
}
|
294
|
+
fflush(stdout);
|
295
|
+
}
|
296
|
+
|
297
|
+
static void
|
298
|
+
do_work(const std::string& connection_string,
|
299
|
+
couchbase::cluster_options& cluster_options,
|
300
|
+
const std::vector<std::string>& statements,
|
301
|
+
const std::optional<scope_with_bucket>& scope_id,
|
302
|
+
const couchbase::query_options& query_options,
|
303
|
+
const console_output_options& output_options)
|
304
|
+
{
|
305
|
+
asio::io_context io;
|
306
|
+
auto guard = asio::make_work_guard(io);
|
307
|
+
std::thread io_thread([&io]() { io.run(); });
|
308
|
+
|
309
|
+
auto [cluster, ec] = couchbase::cluster::connect(io, connection_string, cluster_options).get();
|
310
|
+
if (ec) {
|
311
|
+
throw std::system_error(ec);
|
312
|
+
}
|
313
|
+
|
314
|
+
std::optional<couchbase::scope> scope{};
|
315
|
+
if (scope_id) {
|
316
|
+
scope = cluster.bucket(scope_id->bucket_name).scope(scope_id->scope_name);
|
317
|
+
}
|
318
|
+
|
319
|
+
for (const auto& statement : statements) {
|
320
|
+
auto [ctx, resp] = (scope ? do_query(scope.value(), statement, query_options) : do_query(cluster, statement, query_options)).get();
|
321
|
+
|
322
|
+
if (output_options.json_lines) {
|
323
|
+
print_result_json_line(scope_id, statement, ctx, resp, query_options);
|
324
|
+
} else {
|
325
|
+
print_result(scope_id, statement, ctx, resp, query_options);
|
326
|
+
}
|
327
|
+
}
|
328
|
+
|
329
|
+
cluster.close();
|
330
|
+
guard.reset();
|
331
|
+
|
332
|
+
io_thread.join();
|
333
|
+
}
|
334
|
+
} // namespace
|
335
|
+
|
336
|
+
void
|
337
|
+
cbc::query::execute(const std::vector<std::string>& argv)
|
338
|
+
{
|
339
|
+
try {
|
340
|
+
|
341
|
+
auto options = cbc::parse_options(usage(), argv);
|
342
|
+
if (options["--help"].asBool()) {
|
343
|
+
fmt::print(stdout, usage());
|
344
|
+
return;
|
345
|
+
}
|
346
|
+
|
347
|
+
cbc::apply_logger_options(options);
|
348
|
+
|
349
|
+
couchbase::cluster_options cluster_options{ cbc::default_cluster_options() };
|
350
|
+
std::string connection_string{ cbc::default_connection_string() };
|
351
|
+
cbc::fill_cluster_options(options, cluster_options, connection_string);
|
352
|
+
|
353
|
+
couchbase::query_options query_options{};
|
354
|
+
parse_disable_option(query_options.adhoc, "--prepare");
|
355
|
+
parse_enable_option(query_options.readonly, "--read-only");
|
356
|
+
parse_enable_option(query_options.preserve_expiry, "--preserve-expiry");
|
357
|
+
parse_disable_option(query_options.metrics, "--disable-metrics");
|
358
|
+
parse_enable_option(query_options.flex_index, "--flex-index");
|
359
|
+
parse_integer_option(query_options.max_parallelism, "--maximum-parallelism");
|
360
|
+
parse_integer_option(query_options.scan_cap, "--scan-cap");
|
361
|
+
parse_integer_option(query_options.pipeline_batch, "--pipeline-batch");
|
362
|
+
parse_integer_option(query_options.pipeline_cap, "--pipeline-cap");
|
363
|
+
parse_duration_option(query_options.scan_wait, "--scan-wait");
|
364
|
+
parse_string_option(query_options.client_context_id, "--client-context-id");
|
365
|
+
|
366
|
+
if (options.find("--scan-consistency") != options.end() && options.at("--scan-consistency")) {
|
367
|
+
if (auto value = options.at("--scan-consistency").asString(); value == "not_bounded") {
|
368
|
+
query_options.scan_consistency(couchbase::query_scan_consistency::not_bounded);
|
369
|
+
} else if (value == "request_plus") {
|
370
|
+
query_options.scan_consistency(couchbase::query_scan_consistency::request_plus);
|
371
|
+
} else {
|
372
|
+
throw docopt::DocoptArgumentError(fmt::format("unexpected value '{}' for --scan-consistency", value));
|
373
|
+
}
|
374
|
+
}
|
375
|
+
|
376
|
+
if (options.find("--profile") != options.end() && options.at("--profile")) {
|
377
|
+
if (auto value = options.at("--profile").asString(); value == "off") {
|
378
|
+
query_options.profile(couchbase::query_profile::off);
|
379
|
+
} else if (value == "phases") {
|
380
|
+
query_options.profile(couchbase::query_profile::phases);
|
381
|
+
} else if (value == "timings") {
|
382
|
+
query_options.profile(couchbase::query_profile::phases);
|
383
|
+
} else {
|
384
|
+
throw docopt::DocoptArgumentError(fmt::format("unexpected value '{}' for --profile", value));
|
385
|
+
}
|
386
|
+
}
|
387
|
+
|
388
|
+
std::optional<scope_with_bucket> scope{};
|
389
|
+
if (options.find("--bucket-name") != options.end() && options.at("--bucket-name") &&
|
390
|
+
options.find("--scope-name") != options.end() && options.at("--scope-name")) {
|
391
|
+
scope = { options.at("--bucket-name").asString(), options.at("--scope-name").asString() };
|
392
|
+
}
|
393
|
+
|
394
|
+
static const std::regex named_param_regex{ R"(^([\w\d_]+)=(.*)$)" };
|
395
|
+
if (options.find("--param") != options.end() && options.at("--param")) {
|
396
|
+
std::vector<couchbase::codec::binary> positional_params{};
|
397
|
+
std::map<std::string, couchbase::codec::binary, std::less<>> named_params{};
|
398
|
+
|
399
|
+
for (const auto& param : options.at("--param").asStringList()) {
|
400
|
+
if (std::smatch match; std::regex_match(param, match, named_param_regex)) {
|
401
|
+
named_params[match[1].str()] = std::move(couchbase::core::utils::to_binary(match[2].str()));
|
402
|
+
} else {
|
403
|
+
positional_params.push_back(couchbase::core::utils::to_binary(param));
|
404
|
+
}
|
405
|
+
}
|
406
|
+
if (!positional_params.empty() && !named_params.empty()) {
|
407
|
+
throw docopt::DocoptArgumentError("mixing positional and named parameters is not allowed (parameters must be specified "
|
408
|
+
"either as --param=VALUE or --param=NAME=VALUE)");
|
409
|
+
}
|
410
|
+
if (!positional_params.empty()) {
|
411
|
+
query_options.encoded_positional_parameters(std::move(positional_params));
|
412
|
+
} else if (!named_params.empty()) {
|
413
|
+
query_options.encoded_named_parameters(std::move(named_params));
|
414
|
+
}
|
415
|
+
}
|
416
|
+
if (options.find("--raw") != options.end() && options.at("--raw")) {
|
417
|
+
std::map<std::string, couchbase::codec::binary, std::less<>> raw_params{};
|
418
|
+
for (const auto& param : options.at("--raw").asStringList()) {
|
419
|
+
if (std::smatch match; std::regex_match(param, match, named_param_regex)) {
|
420
|
+
raw_params.emplace(match[1].str(), couchbase::core::utils::to_binary(match[2].str()));
|
421
|
+
} else {
|
422
|
+
throw docopt::DocoptArgumentError("raw parameters should be in NAME=VALUE form, (i.e. --raw=NAME=VALUE)");
|
423
|
+
}
|
424
|
+
}
|
425
|
+
if (!raw_params.empty()) {
|
426
|
+
query_options.encoded_raw_options(raw_params);
|
427
|
+
}
|
428
|
+
}
|
429
|
+
|
430
|
+
console_output_options output_options{};
|
431
|
+
output_options.json_lines = cbc::get_bool_option(options, "--json-lines");
|
432
|
+
|
433
|
+
auto statements{ options["<statement>"].asStringList() };
|
434
|
+
do_work(connection_string, cluster_options, statements, scope, query_options, output_options);
|
435
|
+
} catch (const docopt::DocoptArgumentError& e) {
|
436
|
+
fmt::print(stderr, "Error: {}\n", e.what());
|
437
|
+
} catch (const std::system_error& e) {
|
438
|
+
fmt::print(stderr, "Error: {}\n", e.what());
|
439
|
+
}
|
440
|
+
}
|
441
|
+
} // namespace cbc
|
@@ -0,0 +1,26 @@
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Copyright 2023-Present 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
|
+
#include "command.hxx"
|
19
|
+
|
20
|
+
namespace cbc
|
21
|
+
{
|
22
|
+
class query : public command
|
23
|
+
{
|
24
|
+
void execute(const std::vector<std::string>& argv);
|
25
|
+
};
|
26
|
+
} // namespace cbc
|