couchbase 3.2.4 → 3.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.gyp +5 -0
- package/deps/lcb/CMakeLists.txt +28 -6
- package/deps/lcb/README.markdown +5 -9
- package/deps/lcb/RELEASE_NOTES.markdown +80 -5
- package/deps/lcb/cmake/Modules/GetVersionInfo.cmake +1 -1
- package/deps/lcb/doc/Doxyfile +1 -1
- package/deps/lcb/doc/cbc.markdown +10 -0
- package/deps/lcb/gyp_config/common/libcouchbase/configuration.h +3 -3
- package/deps/lcb/include/libcouchbase/couchbase.h +52 -0
- package/deps/lcb/include/libcouchbase/error.h +5 -2
- package/deps/lcb/libcouchbase.gyp +7 -1
- package/deps/lcb/packaging/rpm/libcouchbase.spec.in +1 -1
- package/deps/lcb/plugins/io/iocp/iocp_iops.h +1 -1
- package/deps/lcb/plugins/io/iocp/iocp_loop.c +3 -3
- package/deps/lcb/plugins/io/iocp/iocp_util.c +2 -2
- package/deps/lcb/src/bucketconfig/bc_file.cc +29 -15
- package/deps/lcb/src/capi/cmd_counter.hh +12 -0
- package/deps/lcb/src/capi/cmd_exists.hh +12 -0
- package/deps/lcb/src/capi/cmd_get.hh +12 -0
- package/deps/lcb/src/capi/cmd_get_replica.hh +14 -1
- package/deps/lcb/src/capi/cmd_query.cc +13 -0
- package/deps/lcb/src/capi/cmd_query.hh +22 -14
- package/deps/lcb/src/capi/cmd_remove.hh +12 -0
- package/deps/lcb/src/capi/cmd_store.hh +12 -0
- package/deps/lcb/src/capi/cmd_subdoc.hh +12 -0
- package/deps/lcb/src/capi/cmd_touch.hh +12 -0
- package/deps/lcb/src/capi/cmd_unlock.hh +12 -0
- package/deps/lcb/src/capi/collection_qualifier.hh +4 -9
- package/deps/lcb/src/instance.cc +19 -0
- package/deps/lcb/src/internal.h +2 -1
- package/deps/lcb/src/mcserver/negotiate.cc +3 -0
- package/deps/lcb/src/n1ql/n1ql.cc +5 -1
- package/deps/lcb/src/n1ql/query_handle.cc +55 -30
- package/deps/lcb/src/n1ql/query_handle.hh +14 -2
- package/deps/lcb/src/operations/counter.cc +12 -0
- package/deps/lcb/src/operations/exists.cc +12 -0
- package/deps/lcb/src/operations/get.cc +12 -0
- package/deps/lcb/src/operations/get_replica.cc +18 -6
- package/deps/lcb/src/operations/ping.cc +2 -2
- package/deps/lcb/src/operations/remove.cc +12 -0
- package/deps/lcb/src/operations/store.cc +12 -0
- package/deps/lcb/src/operations/subdoc.cc +12 -0
- package/deps/lcb/src/operations/touch.cc +12 -0
- package/deps/lcb/src/operations/unlock.cc +12 -0
- package/deps/lcb/src/search/search_handle.cc +1 -2
- package/deps/lcb/src/settings.cc +1 -0
- package/deps/lcb/src/ssl/ssl_common.c +111 -22
- package/deps/lcb/src/utilities.cc +21 -0
- package/deps/lcb/src/utilities.h +3 -0
- package/deps/lcb/src/vbucket/vbucket.c +16 -7
- package/deps/lcb/tests/CMakeLists.txt +1 -1
- package/deps/lcb/tests/iotests/mock-environment.cc +13 -1
- package/deps/lcb/tests/iotests/mock-environment.h +3 -1
- package/deps/lcb/tests/iotests/serverparams.h +7 -2
- package/deps/lcb/tests/iotests/t_ratelimit.cc +739 -0
- package/deps/lcb/tests/iotests/testutil.cc +174 -0
- package/deps/lcb/tests/iotests/testutil.h +53 -0
- package/deps/lcb/tools/CMakeLists.txt +1 -1
- package/deps/lcb/tools/cbc-handlers.h +39 -0
- package/deps/lcb/tools/cbc-n1qlback.cc +1 -0
- package/deps/lcb/tools/cbc-pillowfight.cc +45 -35
- package/deps/lcb/tools/cbc.cc +31 -0
- package/deps/lcb/tools/docgen/docgen.h +11 -10
- package/dist/analyticsexecutor.js +2 -2
- package/dist/analyticsindexmanager.js +3 -3
- package/dist/binarycollection.d.ts +17 -0
- package/dist/binding.js +1 -1
- package/dist/bindingutilities.js +5 -1
- package/dist/bucketmanager.d.ts +1 -22
- package/dist/bucketmanager.js +5 -5
- package/dist/cluster.js +1 -1
- package/dist/collection.js +6 -6
- package/dist/collectionmanager.js +2 -2
- package/dist/connection.js +3 -3
- package/dist/connspec.js +5 -1
- package/dist/couchbase.js +5 -1
- package/dist/httpexecutor.d.ts +1 -0
- package/dist/httpexecutor.js +5 -1
- package/dist/logging.js +1 -1
- package/dist/queryexecutor.js +3 -3
- package/dist/searchindexmanager.js +1 -1
- package/dist/usermanager.js +2 -2
- package/dist/utilities.d.ts +1 -2
- package/dist/utilities.js +9 -2
- package/dist/viewexecutor.js +1 -1
- package/package.json +1 -1
- package/src/uv-plugin-all.cpp +1 -0
- package/dist/cas.d.ts +0 -0
- package/dist/cas.js +0 -1
|
@@ -127,6 +127,17 @@ struct lcb_CMDEXISTS_ {
|
|
|
127
127
|
return LCB_SUCCESS;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
lcb_STATUS on_behalf_of_add_extra_privilege(std::string privilege)
|
|
131
|
+
{
|
|
132
|
+
extra_privileges_.emplace_back(std::move(privilege));
|
|
133
|
+
return LCB_SUCCESS;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const std::vector<std::string> &extra_privileges() const
|
|
137
|
+
{
|
|
138
|
+
return extra_privileges_;
|
|
139
|
+
}
|
|
140
|
+
|
|
130
141
|
bool want_impersonation() const
|
|
131
142
|
{
|
|
132
143
|
return !impostor_.empty();
|
|
@@ -145,6 +156,7 @@ struct lcb_CMDEXISTS_ {
|
|
|
145
156
|
void *cookie_{nullptr};
|
|
146
157
|
std::string key_{};
|
|
147
158
|
std::string impostor_{};
|
|
159
|
+
std::vector<std::string> extra_privileges_{};
|
|
148
160
|
};
|
|
149
161
|
|
|
150
162
|
/**
|
|
@@ -186,6 +186,17 @@ struct lcb_CMDGET_ {
|
|
|
186
186
|
return LCB_SUCCESS;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
lcb_STATUS on_behalf_of_add_extra_privilege(std::string privilege)
|
|
190
|
+
{
|
|
191
|
+
extra_privileges_.emplace_back(std::move(privilege));
|
|
192
|
+
return LCB_SUCCESS;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const std::vector<std::string> &extra_privileges() const
|
|
196
|
+
{
|
|
197
|
+
return extra_privileges_;
|
|
198
|
+
}
|
|
199
|
+
|
|
189
200
|
bool want_impersonation() const
|
|
190
201
|
{
|
|
191
202
|
return !impostor_.empty();
|
|
@@ -208,6 +219,7 @@ struct lcb_CMDGET_ {
|
|
|
208
219
|
get_mode mode_{get_mode::normal};
|
|
209
220
|
bool cookie_is_callback_{false};
|
|
210
221
|
std::string impostor_{};
|
|
222
|
+
std::vector<std::string> extra_privileges_{};
|
|
211
223
|
};
|
|
212
224
|
|
|
213
225
|
/** @private */
|
|
@@ -60,7 +60,8 @@ struct lcb_CMDGETREPLICA_ {
|
|
|
60
60
|
return LCB_SUCCESS;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
int selected_replica_index() const
|
|
63
|
+
int selected_replica_index() const
|
|
64
|
+
{
|
|
64
65
|
return select_index_;
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -162,6 +163,17 @@ struct lcb_CMDGETREPLICA_ {
|
|
|
162
163
|
return LCB_SUCCESS;
|
|
163
164
|
}
|
|
164
165
|
|
|
166
|
+
lcb_STATUS on_behalf_of_add_extra_privilege(std::string privilege)
|
|
167
|
+
{
|
|
168
|
+
extra_privileges_.emplace_back(std::move(privilege));
|
|
169
|
+
return LCB_SUCCESS;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const std::vector<std::string> &extra_privileges() const
|
|
173
|
+
{
|
|
174
|
+
return extra_privileges_;
|
|
175
|
+
}
|
|
176
|
+
|
|
165
177
|
bool want_impersonation() const
|
|
166
178
|
{
|
|
167
179
|
return !impostor_.empty();
|
|
@@ -182,6 +194,7 @@ struct lcb_CMDGETREPLICA_ {
|
|
|
182
194
|
get_replica_mode mode_{get_replica_mode::any};
|
|
183
195
|
int select_index_{0};
|
|
184
196
|
std::string impostor_{};
|
|
197
|
+
std::vector<std::string> extra_privileges_{};
|
|
185
198
|
};
|
|
186
199
|
|
|
187
200
|
struct lcb_RESPGETREPLICA_ {
|
|
@@ -268,6 +268,11 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_on_behalf_of(lcb_CMDQUERY *cmd, const c
|
|
|
268
268
|
return cmd->on_behalf_of(std::string(data, data_len));
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
+
LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_preserve_expiry(lcb_CMDQUERY *cmd, int preserve_expiry)
|
|
272
|
+
{
|
|
273
|
+
return cmd->preserve_expiry(preserve_expiry);
|
|
274
|
+
}
|
|
275
|
+
|
|
271
276
|
LIBCOUCHBASE_API lcb_STATUS lcb_errctx_query_rc(const lcb_QUERY_ERROR_CONTEXT *ctx)
|
|
272
277
|
{
|
|
273
278
|
return ctx->rc;
|
|
@@ -287,6 +292,14 @@ LIBCOUCHBASE_API lcb_STATUS lcb_errctx_query_first_error_message(const lcb_QUERY
|
|
|
287
292
|
return LCB_SUCCESS;
|
|
288
293
|
}
|
|
289
294
|
|
|
295
|
+
LIBCOUCHBASE_API lcb_STATUS lcb_errctx_query_error_response_body(const lcb_QUERY_ERROR_CONTEXT *ctx, const char **body,
|
|
296
|
+
size_t *body_len)
|
|
297
|
+
{
|
|
298
|
+
*body = ctx->error_response_body;
|
|
299
|
+
*body_len = ctx->error_response_body_len;
|
|
300
|
+
return LCB_SUCCESS;
|
|
301
|
+
}
|
|
302
|
+
|
|
290
303
|
LIBCOUCHBASE_API lcb_STATUS lcb_errctx_query_statement(const lcb_QUERY_ERROR_CONTEXT *ctx, const char **statement,
|
|
291
304
|
size_t *statement_len)
|
|
292
305
|
{
|
|
@@ -30,20 +30,22 @@
|
|
|
30
30
|
*/
|
|
31
31
|
struct lcb_QUERY_ERROR_CONTEXT_ {
|
|
32
32
|
lcb_STATUS rc;
|
|
33
|
-
uint32_t first_error_code;
|
|
34
|
-
const char *first_error_message;
|
|
35
|
-
size_t first_error_message_len;
|
|
36
|
-
const char *
|
|
37
|
-
size_t
|
|
38
|
-
const char *
|
|
39
|
-
size_t
|
|
40
|
-
const char *
|
|
41
|
-
size_t
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const char *
|
|
46
|
-
size_t
|
|
33
|
+
uint32_t first_error_code{};
|
|
34
|
+
const char *first_error_message{};
|
|
35
|
+
size_t first_error_message_len{};
|
|
36
|
+
const char *error_response_body{};
|
|
37
|
+
size_t error_response_body_len{};
|
|
38
|
+
const char *statement{};
|
|
39
|
+
size_t statement_len{};
|
|
40
|
+
const char *client_context_id{};
|
|
41
|
+
size_t client_context_id_len{};
|
|
42
|
+
const char *query_params{};
|
|
43
|
+
size_t query_params_len{};
|
|
44
|
+
uint32_t http_response_code{};
|
|
45
|
+
const char *http_response_message{};
|
|
46
|
+
size_t http_response_message_len{};
|
|
47
|
+
const char *endpoint{};
|
|
48
|
+
size_t endpoint_len{};
|
|
47
49
|
};
|
|
48
50
|
|
|
49
51
|
/**
|
|
@@ -203,6 +205,12 @@ struct lcb_CMDQUERY_ {
|
|
|
203
205
|
return LCB_SUCCESS;
|
|
204
206
|
}
|
|
205
207
|
|
|
208
|
+
lcb_STATUS preserve_expiry(bool preserve_expiry)
|
|
209
|
+
{
|
|
210
|
+
root_["preserve_expiry"] = preserve_expiry;
|
|
211
|
+
return LCB_SUCCESS;
|
|
212
|
+
}
|
|
213
|
+
|
|
206
214
|
lcb_STATUS callback(lcb_QUERY_CALLBACK row_callback)
|
|
207
215
|
{
|
|
208
216
|
callback_ = row_callback;
|
|
@@ -154,6 +154,17 @@ struct lcb_CMDREMOVE_ {
|
|
|
154
154
|
return LCB_SUCCESS;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
lcb_STATUS on_behalf_of_add_extra_privilege(std::string privilege)
|
|
158
|
+
{
|
|
159
|
+
extra_privileges_.emplace_back(std::move(privilege));
|
|
160
|
+
return LCB_SUCCESS;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const std::vector<std::string> &extra_privileges() const
|
|
164
|
+
{
|
|
165
|
+
return extra_privileges_;
|
|
166
|
+
}
|
|
167
|
+
|
|
157
168
|
bool want_impersonation() const
|
|
158
169
|
{
|
|
159
170
|
return !impostor_.empty();
|
|
@@ -174,6 +185,7 @@ struct lcb_CMDREMOVE_ {
|
|
|
174
185
|
std::uint64_t cas_{0};
|
|
175
186
|
lcb_DURABILITY_LEVEL durability_level_{LCB_DURABILITYLEVEL_NONE};
|
|
176
187
|
std::string impostor_{};
|
|
188
|
+
std::vector<std::string> extra_privileges_{};
|
|
177
189
|
};
|
|
178
190
|
|
|
179
191
|
/**
|
|
@@ -371,6 +371,17 @@ struct lcb_CMDSTORE_ {
|
|
|
371
371
|
return LCB_SUCCESS;
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
+
lcb_STATUS on_behalf_of_add_extra_privilege(std::string privilege)
|
|
375
|
+
{
|
|
376
|
+
extra_privileges_.emplace_back(std::move(privilege));
|
|
377
|
+
return LCB_SUCCESS;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const std::vector<std::string> &extra_privileges() const
|
|
381
|
+
{
|
|
382
|
+
return extra_privileges_;
|
|
383
|
+
}
|
|
384
|
+
|
|
374
385
|
bool want_impersonation() const
|
|
375
386
|
{
|
|
376
387
|
return !impostor_.empty();
|
|
@@ -402,6 +413,7 @@ struct lcb_CMDSTORE_ {
|
|
|
402
413
|
bool cookie_is_callback_{false};
|
|
403
414
|
bool preserve_expiry_{false};
|
|
404
415
|
std::string impostor_{};
|
|
416
|
+
std::vector<std::string> extra_privileges_{};
|
|
405
417
|
};
|
|
406
418
|
|
|
407
419
|
/**
|
|
@@ -445,6 +445,17 @@ struct lcb_CMDSUBDOC_ {
|
|
|
445
445
|
return LCB_SUCCESS;
|
|
446
446
|
}
|
|
447
447
|
|
|
448
|
+
lcb_STATUS on_behalf_of_add_extra_privilege(std::string privilege)
|
|
449
|
+
{
|
|
450
|
+
extra_privileges_.emplace_back(std::move(privilege));
|
|
451
|
+
return LCB_SUCCESS;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const std::vector<std::string> &extra_privileges() const
|
|
455
|
+
{
|
|
456
|
+
return extra_privileges_;
|
|
457
|
+
}
|
|
458
|
+
|
|
448
459
|
bool want_impersonation() const
|
|
449
460
|
{
|
|
450
461
|
return !impostor_.empty();
|
|
@@ -469,6 +480,7 @@ struct lcb_CMDSUBDOC_ {
|
|
|
469
480
|
lcb_SUBDOCSPECS_ specs_{};
|
|
470
481
|
bool preserve_expiry_{false};
|
|
471
482
|
std::string impostor_{};
|
|
483
|
+
std::vector<std::string> extra_privileges_{};
|
|
472
484
|
};
|
|
473
485
|
|
|
474
486
|
/**
|
|
@@ -138,6 +138,17 @@ struct lcb_CMDTOUCH_ {
|
|
|
138
138
|
return LCB_SUCCESS;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
lcb_STATUS on_behalf_of_add_extra_privilege(std::string privilege)
|
|
142
|
+
{
|
|
143
|
+
extra_privileges_.emplace_back(std::move(privilege));
|
|
144
|
+
return LCB_SUCCESS;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const std::vector<std::string> &extra_privileges() const
|
|
148
|
+
{
|
|
149
|
+
return extra_privileges_;
|
|
150
|
+
}
|
|
151
|
+
|
|
141
152
|
bool want_impersonation() const
|
|
142
153
|
{
|
|
143
154
|
return !impostor_.empty();
|
|
@@ -157,6 +168,7 @@ struct lcb_CMDTOUCH_ {
|
|
|
157
168
|
void *cookie_{nullptr};
|
|
158
169
|
std::string key_{};
|
|
159
170
|
std::string impostor_{};
|
|
171
|
+
std::vector<std::string> extra_privileges_{};
|
|
160
172
|
};
|
|
161
173
|
|
|
162
174
|
/**
|
|
@@ -141,6 +141,17 @@ struct lcb_CMDUNLOCK_ {
|
|
|
141
141
|
return LCB_SUCCESS;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
lcb_STATUS on_behalf_of_add_extra_privilege(std::string privilege)
|
|
145
|
+
{
|
|
146
|
+
extra_privileges_.emplace_back(std::move(privilege));
|
|
147
|
+
return LCB_SUCCESS;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const std::vector<std::string> &extra_privileges() const
|
|
151
|
+
{
|
|
152
|
+
return extra_privileges_;
|
|
153
|
+
}
|
|
154
|
+
|
|
144
155
|
bool want_impersonation() const
|
|
145
156
|
{
|
|
146
157
|
return !impostor_.empty();
|
|
@@ -160,6 +171,7 @@ struct lcb_CMDUNLOCK_ {
|
|
|
160
171
|
std::string key_{};
|
|
161
172
|
std::uint64_t cas_{};
|
|
162
173
|
std::string impostor_{};
|
|
174
|
+
std::vector<std::string> extra_privileges_{};
|
|
163
175
|
};
|
|
164
176
|
|
|
165
177
|
/**
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
#include <cstddef>
|
|
22
22
|
#include <cstdint>
|
|
23
23
|
#include <string>
|
|
24
|
-
#include <sstream>
|
|
25
24
|
#include <stdexcept>
|
|
26
25
|
|
|
27
26
|
namespace lcb
|
|
@@ -48,11 +47,10 @@ struct collection_qualifier {
|
|
|
48
47
|
if (collection_name != nullptr && collection_name_len > 0) {
|
|
49
48
|
collection_.assign(collection_name, collection_name_len);
|
|
50
49
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
spec_ = ss.str();
|
|
50
|
+
|
|
51
|
+
spec_ = (scope_.empty() ? "_default" : scope_) +
|
|
52
|
+
'.' +
|
|
53
|
+
(collection_.empty() ? "_default" : collection_);
|
|
56
54
|
}
|
|
57
55
|
|
|
58
56
|
const std::string &scope() const
|
|
@@ -124,9 +122,6 @@ struct collection_qualifier {
|
|
|
124
122
|
/* nullptr/0 for collection is mapped to default collection */
|
|
125
123
|
return true;
|
|
126
124
|
}
|
|
127
|
-
if (element_len < 1 || element_len > 30) {
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
125
|
for (size_t i = 0; i < element_len; ++i) {
|
|
131
126
|
if (!is_valid_collection_char(element[i])) {
|
|
132
127
|
return false;
|
package/deps/lcb/src/instance.cc
CHANGED
|
@@ -466,6 +466,25 @@ lcb_STATUS lcb_create(lcb_INSTANCE **instance, const lcb_CREATEOPTS *options)
|
|
|
466
466
|
goto GT_DONE;
|
|
467
467
|
}
|
|
468
468
|
|
|
469
|
+
{
|
|
470
|
+
// Warn users if they attempt to use Capella without TLS being enabled.
|
|
471
|
+
bool is_capella = false;
|
|
472
|
+
static std::string suffix = "cloud.couchbase.com";
|
|
473
|
+
for (auto &node : spec.hosts()) {
|
|
474
|
+
auto pos = node.hostname.find(suffix);
|
|
475
|
+
if (pos != std::string::npos && pos + suffix.size() == node.hostname.size()) {
|
|
476
|
+
is_capella = true;
|
|
477
|
+
break;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (is_capella && (spec.sslopts() & LCB_SSL_ENABLED) == 0) {
|
|
482
|
+
lcb_log(LOGARGS(obj, INFO),
|
|
483
|
+
"TLS is required when connecting to Couchbase Capella. Please enable TLS by prefixing "
|
|
484
|
+
"the connection string with \"couchbases://\" (note the final 's').");
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
469
488
|
if ((obj = (lcb_INSTANCE *)calloc(1, sizeof(*obj))) == nullptr) {
|
|
470
489
|
err = LCB_ERR_NO_MEMORY;
|
|
471
490
|
goto GT_DONE;
|
package/deps/lcb/src/internal.h
CHANGED
|
@@ -259,7 +259,8 @@ lcb_STATUS lcb_initialize_socket_subsystem(void);
|
|
|
259
259
|
lcb_STATUS lcb_reinit(lcb_INSTANCE *obj, const char *connstr);
|
|
260
260
|
|
|
261
261
|
lcb_RETRY_ACTION lcb_kv_should_retry(const lcb_settings *settings, const mc_PACKET *pkt, lcb_STATUS err);
|
|
262
|
-
lcb_RETRY_ACTION lcb_query_should_retry(const lcb_settings *settings, lcb_QUERY_HANDLE *query, lcb_STATUS err
|
|
262
|
+
lcb_RETRY_ACTION lcb_query_should_retry(const lcb_settings *settings, lcb_QUERY_HANDLE *query, lcb_STATUS err,
|
|
263
|
+
int retry_attribute);
|
|
263
264
|
|
|
264
265
|
lcb_RESPCALLBACK lcb_find_callback(lcb_INSTANCE *instance, lcb_CALLBACK_TYPE cbtype);
|
|
265
266
|
|
|
@@ -660,6 +660,9 @@ GT_NEXT_PACKET:
|
|
|
660
660
|
status);
|
|
661
661
|
set_error(LCB_ERR_PROTOCOL_ERROR, "GET_ERRMAP response unexpected", &resp);
|
|
662
662
|
}
|
|
663
|
+
if (settings->keypath) {
|
|
664
|
+
completed = !maybe_select_bucket();
|
|
665
|
+
}
|
|
663
666
|
// Note, there is no explicit state transition here. LIST_MECHS is
|
|
664
667
|
// pipelined after this request.
|
|
665
668
|
break;
|
|
@@ -52,10 +52,14 @@ static lcb_RETRY_REASON query_code_to_reason(lcb_STATUS err)
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
lcb_RETRY_ACTION lcb_query_should_retry(const lcb_settings *settings, lcb_QUERY_HANDLE *query, lcb_STATUS err
|
|
55
|
+
lcb_RETRY_ACTION lcb_query_should_retry(const lcb_settings *settings, lcb_QUERY_HANDLE *query, lcb_STATUS err,
|
|
56
|
+
int retry_attribute)
|
|
56
57
|
{
|
|
57
58
|
lcb_RETRY_ACTION retry_action{};
|
|
58
59
|
lcb_RETRY_REASON retry_reason = query_code_to_reason(err);
|
|
60
|
+
if (retry_attribute) {
|
|
61
|
+
retry_reason = LCB_RETRY_REASON_QUERY_ERROR_RETRYABLE;
|
|
62
|
+
}
|
|
59
63
|
if (err == LCB_ERR_TIMEOUT) {
|
|
60
64
|
/* We can't exceed a timeout for ETIMEDOUT */
|
|
61
65
|
retry_action.should_retry = 0;
|
|
@@ -95,8 +95,8 @@ static void prepare_rowcb(lcb_INSTANCE *instance, int, const lcb_RESPQUERY *row)
|
|
|
95
95
|
|
|
96
96
|
bool lcb_QUERY_HANDLE_::parse_meta(const char *row, size_t row_len, lcb_STATUS &rc)
|
|
97
97
|
{
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
first_error.message.clear();
|
|
99
|
+
first_error.code = 0;
|
|
100
100
|
|
|
101
101
|
Json::Value meta;
|
|
102
102
|
if (!Json::Reader(Json::Features::strictMode()).parse(row, row + row_len, meta)) {
|
|
@@ -105,22 +105,42 @@ bool lcb_QUERY_HANDLE_::parse_meta(const char *row, size_t row_len, lcb_STATUS &
|
|
|
105
105
|
const Json::Value &errors = meta["errors"];
|
|
106
106
|
if (errors.isArray() && !errors.empty()) {
|
|
107
107
|
const Json::Value &err = errors[0];
|
|
108
|
+
if (err.isMember("retry") && err["retry"].isBool()) {
|
|
109
|
+
first_error.retry = err["retry"].asBool();
|
|
110
|
+
}
|
|
111
|
+
if (err.isMember("reason") && err["reason"].isObject()) {
|
|
112
|
+
const Json::Value &reason = err["reason"];
|
|
113
|
+
if (reason.isMember("code") && reason["code"].isNumeric()) {
|
|
114
|
+
first_error.reason_code = reason["code"].asInt();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
108
117
|
const Json::Value &msg = err["msg"];
|
|
109
118
|
if (msg.isString()) {
|
|
110
|
-
|
|
119
|
+
first_error.message = msg.asString();
|
|
111
120
|
}
|
|
112
121
|
const Json::Value &code = err["code"];
|
|
113
122
|
if (code.isNumeric()) {
|
|
114
|
-
|
|
115
|
-
switch (
|
|
123
|
+
first_error.code = code.asUInt();
|
|
124
|
+
switch (first_error.code) {
|
|
116
125
|
case 3000:
|
|
117
126
|
rc = LCB_ERR_PARSING_FAILURE;
|
|
118
127
|
break;
|
|
119
128
|
case 12009:
|
|
120
129
|
rc = LCB_ERR_DML_FAILURE;
|
|
121
|
-
if (
|
|
130
|
+
if (first_error.message.find("CAS mismatch") != std::string::npos) {
|
|
122
131
|
rc = LCB_ERR_CAS_MISMATCH;
|
|
123
132
|
}
|
|
133
|
+
switch (first_error.reason_code) {
|
|
134
|
+
case 12033:
|
|
135
|
+
rc = LCB_ERR_CAS_MISMATCH;
|
|
136
|
+
break;
|
|
137
|
+
case 17014:
|
|
138
|
+
rc = LCB_ERR_DOCUMENT_NOT_FOUND;
|
|
139
|
+
break;
|
|
140
|
+
case 17012:
|
|
141
|
+
rc = LCB_ERR_DOCUMENT_EXISTS;
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
124
144
|
break;
|
|
125
145
|
case 4040:
|
|
126
146
|
case 4050:
|
|
@@ -132,31 +152,34 @@ bool lcb_QUERY_HANDLE_::parse_meta(const char *row, size_t row_len, lcb_STATUS &
|
|
|
132
152
|
break;
|
|
133
153
|
case 4300:
|
|
134
154
|
rc = LCB_ERR_PLANNING_FAILURE;
|
|
135
|
-
if (!
|
|
155
|
+
if (!first_error.message.empty()) {
|
|
136
156
|
std::regex already_exists("index.+already exists");
|
|
137
|
-
if (std::regex_search(
|
|
157
|
+
if (std::regex_search(first_error.message, already_exists)) {
|
|
138
158
|
rc = LCB_ERR_INDEX_EXISTS;
|
|
139
159
|
}
|
|
140
160
|
}
|
|
141
161
|
break;
|
|
142
162
|
case 5000:
|
|
143
163
|
rc = LCB_ERR_INTERNAL_SERVER_FAILURE;
|
|
144
|
-
if (!
|
|
164
|
+
if (!first_error.message.empty()) {
|
|
145
165
|
std::regex already_exists("Index.+already exists"); /* NOTE: case sensitive */
|
|
146
166
|
std::regex not_found("index.+not found");
|
|
147
|
-
if (std::regex_search(
|
|
167
|
+
if (std::regex_search(first_error.message, already_exists)) {
|
|
148
168
|
rc = LCB_ERR_INDEX_EXISTS;
|
|
149
|
-
} else if (std::regex_search(
|
|
169
|
+
} else if (std::regex_search(first_error.message, not_found)) {
|
|
150
170
|
rc = LCB_ERR_INDEX_NOT_FOUND;
|
|
151
|
-
} else if (
|
|
171
|
+
} else if (first_error.message.find(
|
|
152
172
|
"Limit for number of indexes that can be created per scope has been reached") !=
|
|
153
173
|
std::string::npos) {
|
|
154
174
|
rc = LCB_ERR_QUOTA_LIMITED;
|
|
155
175
|
}
|
|
156
176
|
}
|
|
157
177
|
break;
|
|
158
|
-
case 12004:
|
|
159
178
|
case 12016:
|
|
179
|
+
/* see MB-50643 */
|
|
180
|
+
first_error.retry = false;
|
|
181
|
+
/* fallthrough */
|
|
182
|
+
case 12004:
|
|
160
183
|
rc = LCB_ERR_INDEX_NOT_FOUND;
|
|
161
184
|
break;
|
|
162
185
|
case 12003:
|
|
@@ -177,14 +200,14 @@ bool lcb_QUERY_HANDLE_::parse_meta(const char *row, size_t row_len, lcb_STATUS &
|
|
|
177
200
|
break;
|
|
178
201
|
|
|
179
202
|
default:
|
|
180
|
-
if (
|
|
203
|
+
if (first_error.code >= 4000 && first_error.code < 5000) {
|
|
181
204
|
rc = LCB_ERR_PLANNING_FAILURE;
|
|
182
|
-
} else if (
|
|
205
|
+
} else if (first_error.code >= 5000 && first_error.code < 6000) {
|
|
183
206
|
rc = LCB_ERR_INTERNAL_SERVER_FAILURE;
|
|
184
|
-
} else if (
|
|
207
|
+
} else if (first_error.code >= 10000 && first_error.code < 11000) {
|
|
185
208
|
rc = LCB_ERR_AUTHENTICATION_FAILURE;
|
|
186
|
-
} else if ((
|
|
187
|
-
(
|
|
209
|
+
} else if ((first_error.code >= 12000 && first_error.code < 13000) ||
|
|
210
|
+
(first_error.code >= 14000 && first_error.code < 15000)) {
|
|
188
211
|
rc = LCB_ERR_INDEX_FAILURE;
|
|
189
212
|
}
|
|
190
213
|
break;
|
|
@@ -218,11 +241,13 @@ void lcb_QUERY_HANDLE_::invoke_row(lcb_RESPQUERY *resp, bool is_last)
|
|
|
218
241
|
resp->row = static_cast<const char *>(meta_buf.iov_base);
|
|
219
242
|
resp->nrow = meta_buf.iov_len;
|
|
220
243
|
parse_meta(resp->row, resp->nrow, resp->ctx.rc);
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
244
|
+
resp->ctx.error_response_body = resp->row;
|
|
245
|
+
resp->ctx.error_response_body_len = resp->nrow;
|
|
246
|
+
if (!first_error.message.empty()) {
|
|
247
|
+
resp->ctx.first_error_message = first_error.message.c_str();
|
|
248
|
+
resp->ctx.first_error_message_len = first_error.message.size();
|
|
224
249
|
}
|
|
225
|
-
resp->ctx.first_error_code =
|
|
250
|
+
resp->ctx.first_error_code = first_error.code;
|
|
226
251
|
if (span_ != nullptr) {
|
|
227
252
|
lcb::trace::finish_http_span(span_, this);
|
|
228
253
|
span_ = nullptr;
|
|
@@ -358,27 +383,27 @@ lcb_RETRY_ACTION lcb_QUERY_HANDLE_::has_retriable_error(lcb_STATUS &rc)
|
|
|
358
383
|
const uint32_t default_backoff = 100 /* ms */;
|
|
359
384
|
if (rc == LCB_ERR_PREPARED_STATEMENT_FAILURE) {
|
|
360
385
|
lcb_log(LOGARGS(this, TRACE), LOGFMT "Will retry request. rc: %s, code: %d, msg: %s", LOGID(this),
|
|
361
|
-
lcb_strerror_short(rc),
|
|
386
|
+
lcb_strerror_short(rc), first_error.code, first_error.message.c_str());
|
|
362
387
|
return {1, default_backoff};
|
|
363
388
|
}
|
|
364
|
-
if (
|
|
389
|
+
if (first_error.code == 13014 &&
|
|
365
390
|
LCBT_SETTING(instance_, auth)->mode() == LCBAUTH_MODE_DYNAMIC) { // datastore.couchbase.insufficient_credentials
|
|
366
391
|
auto result = request_credentials(LCBAUTH_REASON_AUTHENTICATION_FAILURE);
|
|
367
392
|
bool credentials_found = result == LCBAUTH_RESULT_OK;
|
|
368
393
|
lcb_log(LOGARGS(this, TRACE),
|
|
369
394
|
LOGFMT "Invalidate credentials and retry request. creds: %s, rc: %s, code: %d, msg: %s", LOGID(this),
|
|
370
|
-
credentials_found ? "ok" : "not_found", lcb_strerror_short(rc),
|
|
371
|
-
|
|
395
|
+
credentials_found ? "ok" : "not_found", lcb_strerror_short(rc), first_error.code,
|
|
396
|
+
first_error.message.c_str());
|
|
372
397
|
return {credentials_found, default_backoff};
|
|
373
398
|
}
|
|
374
|
-
if (!
|
|
399
|
+
if (!first_error.message.empty()) {
|
|
375
400
|
for (const auto &magic_string : wtf_magic_strings) {
|
|
376
|
-
if (
|
|
401
|
+
if (first_error.message.find(magic_string) != std::string::npos) {
|
|
377
402
|
lcb_log(LOGARGS(this, TRACE),
|
|
378
403
|
LOGFMT
|
|
379
404
|
"Special error message detected. Will retry request. rc: %s (update to %s), code: %d, msg: %s",
|
|
380
405
|
LOGID(this), lcb_strerror_short(rc), lcb_strerror_short(LCB_ERR_PREPARED_STATEMENT_FAILURE),
|
|
381
|
-
|
|
406
|
+
first_error.code, first_error.message.c_str());
|
|
382
407
|
rc = LCB_ERR_PREPARED_STATEMENT_FAILURE;
|
|
383
408
|
return {1, default_backoff};
|
|
384
409
|
}
|
|
@@ -388,7 +413,7 @@ lcb_RETRY_ACTION lcb_QUERY_HANDLE_::has_retriable_error(lcb_STATUS &rc)
|
|
|
388
413
|
if (rc == LCB_SUCCESS) {
|
|
389
414
|
return {0, 0};
|
|
390
415
|
}
|
|
391
|
-
return lcb_query_should_retry(instance_->settings, this, rc);
|
|
416
|
+
return lcb_query_should_retry(instance_->settings, this, rc, first_error.retry);
|
|
392
417
|
}
|
|
393
418
|
|
|
394
419
|
lcb_STATUS lcb_QUERY_HANDLE_::issue_htreq(const std::string &body)
|
|
@@ -27,6 +27,19 @@
|
|
|
27
27
|
#include "capi/cmd_query.hh"
|
|
28
28
|
#include "query_cache.hh"
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
namespace lcb
|
|
34
|
+
{
|
|
35
|
+
struct query_error {
|
|
36
|
+
std::string message{};
|
|
37
|
+
uint32_t code{};
|
|
38
|
+
bool retry{false};
|
|
39
|
+
uint32_t reason_code{0};
|
|
40
|
+
};
|
|
41
|
+
} // namespace lcb
|
|
42
|
+
|
|
30
43
|
/**
|
|
31
44
|
* @private
|
|
32
45
|
*/
|
|
@@ -296,8 +309,7 @@ struct lcb_QUERY_HANDLE_ : lcb::jsparse::Parser::Actions {
|
|
|
296
309
|
/** String of the original statement. Cached here to avoid jsoncpp lookups */
|
|
297
310
|
std::string statement_;
|
|
298
311
|
std::string client_context_id_;
|
|
299
|
-
|
|
300
|
-
uint32_t first_error_code{};
|
|
312
|
+
lcb::query_error first_error{};
|
|
301
313
|
|
|
302
314
|
/** Whether we're retrying this */
|
|
303
315
|
int retries_{0};
|
|
@@ -141,6 +141,12 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_on_behalf_of(lcb_CMDCOUNTER *cmd, con
|
|
|
141
141
|
return cmd->on_behalf_of(std::string(data, data_len));
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_on_behalf_of_extra_privilege(lcb_CMDCOUNTER *cmd, const char *privilege,
|
|
145
|
+
size_t privilege_len)
|
|
146
|
+
{
|
|
147
|
+
return cmd->on_behalf_of_add_extra_privilege(std::string(privilege, privilege_len));
|
|
148
|
+
}
|
|
149
|
+
|
|
144
150
|
static lcb_STATUS counter_validate(lcb_INSTANCE *instance, const lcb_CMDCOUNTER *cmd)
|
|
145
151
|
{
|
|
146
152
|
if (cmd->key().empty()) {
|
|
@@ -184,6 +190,12 @@ static lcb_STATUS counter_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_C
|
|
|
184
190
|
if (err != LCB_SUCCESS) {
|
|
185
191
|
return err;
|
|
186
192
|
}
|
|
193
|
+
for (const auto &privilege : cmd->extra_privileges()) {
|
|
194
|
+
err = lcb::flexible_framing_extras::encode_impersonate_users_extra_privilege(privilege, framing_extras);
|
|
195
|
+
if (err != LCB_SUCCESS) {
|
|
196
|
+
return err;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
187
199
|
}
|
|
188
200
|
|
|
189
201
|
hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
|
|
@@ -112,6 +112,12 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdexists_on_behalf_of(lcb_CMDEXISTS *cmd, const
|
|
|
112
112
|
return cmd->on_behalf_of(std::string(data, data_len));
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
LIBCOUCHBASE_API lcb_STATUS lcb_cmdexists_on_behalf_of_extra_privilege(lcb_CMDEXISTS *cmd, const char *privilege,
|
|
116
|
+
size_t privilege_len)
|
|
117
|
+
{
|
|
118
|
+
return cmd->on_behalf_of_add_extra_privilege(std::string(privilege, privilege_len));
|
|
119
|
+
}
|
|
120
|
+
|
|
115
121
|
static lcb_STATUS exists_validate(lcb_INSTANCE *instance, const lcb_CMDEXISTS *cmd)
|
|
116
122
|
{
|
|
117
123
|
if (cmd->key().empty()) {
|
|
@@ -139,6 +145,12 @@ static lcb_STATUS exists_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
|
|
|
139
145
|
if (err != LCB_SUCCESS) {
|
|
140
146
|
return err;
|
|
141
147
|
}
|
|
148
|
+
for (const auto &privilege : cmd->extra_privileges()) {
|
|
149
|
+
err = lcb::flexible_framing_extras::encode_impersonate_users_extra_privilege(privilege, framing_extras);
|
|
150
|
+
if (err != LCB_SUCCESS) {
|
|
151
|
+
return err;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
142
154
|
}
|
|
143
155
|
|
|
144
156
|
hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
|