couchbase 3.4.4 → 3.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/ext/couchbase/CMakeLists.txt +7 -0
- data/ext/couchbase/core/cluster.hxx +7 -0
- data/ext/couchbase/core/impl/create_bucket.cxx +3 -0
- data/ext/couchbase/core/impl/create_collection.cxx +83 -0
- data/ext/couchbase/core/impl/create_scope.cxx +69 -0
- data/ext/couchbase/core/impl/drop_collection.cxx +76 -0
- data/ext/couchbase/core/impl/drop_scope.cxx +68 -0
- data/ext/couchbase/core/impl/get_all_buckets.cxx +19 -4
- data/ext/couchbase/core/impl/get_all_scopes.cxx +94 -0
- data/ext/couchbase/core/impl/get_bucket.cxx +19 -4
- data/ext/couchbase/core/impl/lookup_in_all_replicas.cxx +2 -0
- data/ext/couchbase/core/impl/lookup_in_any_replica.cxx +2 -0
- data/ext/couchbase/core/impl/lookup_in_replica.cxx +8 -1
- data/ext/couchbase/core/impl/update_bucket.cxx +3 -0
- data/ext/couchbase/core/impl/update_collection.cxx +83 -0
- data/ext/couchbase/core/management/bucket_settings.hxx +8 -5
- data/ext/couchbase/core/management/bucket_settings_json.hxx +12 -2
- data/ext/couchbase/core/meta/features.hxx +17 -0
- data/ext/couchbase/core/operations/document_lookup_in.cxx +8 -1
- data/ext/couchbase/core/operations/management/CMakeLists.txt +1 -0
- data/ext/couchbase/core/operations/management/bucket_create.cxx +30 -9
- data/ext/couchbase/core/operations/management/bucket_update.cxx +27 -6
- data/ext/couchbase/core/operations/management/collection_create.cxx +5 -1
- data/ext/couchbase/core/operations/management/collection_create.hxx +1 -0
- data/ext/couchbase/core/operations/management/collection_update.cxx +87 -0
- data/ext/couchbase/core/operations/management/collection_update.hxx +54 -0
- data/ext/couchbase/core/operations/management/collections.hxx +1 -0
- data/ext/couchbase/core/timeout_defaults.hxx +1 -1
- data/ext/couchbase/core/topology/capabilities.hxx +1 -0
- data/ext/couchbase/core/topology/capabilities_fmt.hxx +3 -0
- data/ext/couchbase/core/topology/collections_manifest.hxx +2 -0
- data/ext/couchbase/core/topology/collections_manifest_json.hxx +3 -0
- data/ext/couchbase/core/topology/configuration.hxx +5 -0
- data/ext/couchbase/core/topology/configuration_json.hxx +2 -0
- data/ext/couchbase/couchbase/bucket.hxx +14 -0
- data/ext/couchbase/couchbase/collection_manager.hxx +160 -0
- data/ext/couchbase/couchbase/create_collection_options.hxx +44 -0
- data/ext/couchbase/couchbase/create_scope_options.hxx +41 -0
- data/ext/couchbase/couchbase/drop_collection_options.hxx +41 -0
- data/ext/couchbase/couchbase/drop_scope_options.hxx +41 -0
- data/ext/couchbase/couchbase/get_all_scopes_options.hxx +44 -0
- data/ext/couchbase/couchbase/management/bucket_settings.hxx +8 -5
- data/ext/couchbase/couchbase/management/collection_spec.hxx +29 -0
- data/ext/couchbase/couchbase/management/scope_spec.hxx +29 -0
- data/ext/couchbase/couchbase/update_collection_options.hxx +44 -0
- data/ext/couchbase/test/test_integration_management.cxx +305 -48
- data/ext/couchbase/test/test_integration_subdoc.cxx +81 -22
- data/ext/couchbase.cxx +155 -34
- data/ext/revisions.rb +3 -3
- data/lib/couchbase/collection_options.rb +1 -2
- data/lib/couchbase/management/bucket_manager.rb +22 -15
- data/lib/couchbase/management/collection_manager.rb +158 -9
- data/lib/couchbase/version.rb +1 -1
- metadata +23 -6
@@ -49,7 +49,8 @@ assert_single_lookup_error(test::utils::integration_test_guard& integration,
|
|
49
49
|
const couchbase::core::document_id& id,
|
50
50
|
const SubdocumentOperation& spec,
|
51
51
|
couchbase::key_value_status_code expected_status,
|
52
|
-
std::error_code expected_ec
|
52
|
+
std::error_code expected_ec,
|
53
|
+
std::optional<std::string> expected_value = std::nullopt)
|
53
54
|
{
|
54
55
|
couchbase::core::operations::lookup_in_request req{ id };
|
55
56
|
req.specs = couchbase::lookup_in_specs{ spec }.specs();
|
@@ -60,9 +61,13 @@ assert_single_lookup_error(test::utils::integration_test_guard& integration,
|
|
60
61
|
REQUIRE(resp.fields.size() == 1);
|
61
62
|
REQUIRE_FALSE(resp.fields[0].exists);
|
62
63
|
REQUIRE(resp.fields[0].path == req.specs[0].path_);
|
63
|
-
REQUIRE(resp.fields[0].value.empty());
|
64
64
|
REQUIRE(resp.fields[0].status == expected_status);
|
65
65
|
REQUIRE(resp.fields[0].ec == expected_ec);
|
66
|
+
if (expected_value.has_value()) {
|
67
|
+
REQUIRE(couchbase::core::utils::to_binary(expected_value.value()) == resp.fields[0].value);
|
68
|
+
} else {
|
69
|
+
REQUIRE(resp.fields[0].value.empty());
|
70
|
+
}
|
66
71
|
}
|
67
72
|
|
68
73
|
template<typename SubdocumentOperation>
|
@@ -85,6 +90,8 @@ assert_single_lookup_any_replica_success(test::utils::integration_test_guard& in
|
|
85
90
|
REQUIRE_SUCCESS(resp.fields[0].ec);
|
86
91
|
if (expected_value.has_value()) {
|
87
92
|
REQUIRE(couchbase::core::utils::to_binary(expected_value.value()) == resp.fields[0].value);
|
93
|
+
} else {
|
94
|
+
REQUIRE(resp.fields[0].value.empty());
|
88
95
|
}
|
89
96
|
}
|
90
97
|
|
@@ -94,20 +101,25 @@ assert_single_lookup_any_replica_error(test::utils::integration_test_guard& inte
|
|
94
101
|
const couchbase::core::document_id& id,
|
95
102
|
const SubdocumentOperation& spec,
|
96
103
|
couchbase::key_value_status_code expected_status,
|
97
|
-
std::error_code expected_ec
|
104
|
+
std::error_code expected_ec,
|
105
|
+
std::optional<std::string> expected_value = std::nullopt)
|
98
106
|
{
|
99
107
|
couchbase::core::operations::lookup_in_any_replica_request req{ id };
|
100
108
|
req.specs = couchbase::lookup_in_specs{ spec }.specs();
|
101
109
|
auto resp = test::utils::execute(integration.cluster, req);
|
102
|
-
INFO(fmt::format("
|
110
|
+
INFO(fmt::format("assert_single_lookup_any_replica_error(\"{}\", \"{}\")", id, req.specs[0].path_));
|
103
111
|
REQUIRE_SUCCESS(resp.ctx.ec());
|
104
112
|
REQUIRE_FALSE(resp.cas.empty());
|
105
113
|
REQUIRE(resp.fields.size() == 1);
|
106
114
|
REQUIRE_FALSE(resp.fields[0].exists);
|
107
115
|
REQUIRE(resp.fields[0].path == req.specs[0].path_);
|
108
|
-
REQUIRE(resp.fields[0].value.empty());
|
109
116
|
REQUIRE(resp.fields[0].status == expected_status);
|
110
117
|
REQUIRE(resp.fields[0].ec == expected_ec);
|
118
|
+
if (expected_value.has_value()) {
|
119
|
+
REQUIRE(couchbase::core::utils::to_binary(expected_value.value()) == resp.fields[0].value);
|
120
|
+
} else {
|
121
|
+
REQUIRE(resp.fields[0].value.empty());
|
122
|
+
}
|
111
123
|
}
|
112
124
|
|
113
125
|
template<typename SubdocumentOperation>
|
@@ -145,7 +157,8 @@ assert_single_lookup_all_replica_error(test::utils::integration_test_guard& inte
|
|
145
157
|
const couchbase::core::document_id& id,
|
146
158
|
const SubdocumentOperation& spec,
|
147
159
|
couchbase::key_value_status_code expected_status,
|
148
|
-
std::error_code expected_ec
|
160
|
+
std::error_code expected_ec,
|
161
|
+
std::optional<std::string> expected_value = std::nullopt)
|
149
162
|
{
|
150
163
|
couchbase::core::operations::lookup_in_all_replicas_request req{ id };
|
151
164
|
req.specs = couchbase::lookup_in_specs{ spec }.specs();
|
@@ -161,9 +174,13 @@ assert_single_lookup_all_replica_error(test::utils::integration_test_guard& inte
|
|
161
174
|
REQUIRE(resp.fields.size() == 1);
|
162
175
|
REQUIRE_FALSE(resp.fields[0].exists);
|
163
176
|
REQUIRE(resp.fields[0].path == req.specs[0].path_);
|
164
|
-
REQUIRE(resp.fields[0].value.empty());
|
165
177
|
REQUIRE(resp.fields[0].status == expected_status);
|
166
178
|
REQUIRE(resp.fields[0].ec == expected_ec);
|
179
|
+
if (expected_value.has_value()) {
|
180
|
+
REQUIRE(couchbase::core::utils::to_binary(expected_value.value()) == resp.fields[0].value);
|
181
|
+
} else {
|
182
|
+
REQUIRE(resp.fields[0].value.empty());
|
183
|
+
}
|
167
184
|
}
|
168
185
|
}
|
169
186
|
|
@@ -214,7 +231,7 @@ TEST_CASE("integration: subdoc get & exists", "[integration]")
|
|
214
231
|
|
215
232
|
SECTION("dict exists")
|
216
233
|
{
|
217
|
-
assert_single_lookup_success(integration, id, couchbase::lookup_in_specs::exists("dictkey"));
|
234
|
+
assert_single_lookup_success(integration, id, couchbase::lookup_in_specs::exists("dictkey"), "true");
|
218
235
|
}
|
219
236
|
|
220
237
|
SECTION("array get")
|
@@ -224,7 +241,7 @@ TEST_CASE("integration: subdoc get & exists", "[integration]")
|
|
224
241
|
|
225
242
|
SECTION("array exists")
|
226
243
|
{
|
227
|
-
assert_single_lookup_success(integration, id, couchbase::lookup_in_specs::exists("array"));
|
244
|
+
assert_single_lookup_success(integration, id, couchbase::lookup_in_specs::exists("array"), "true");
|
228
245
|
}
|
229
246
|
|
230
247
|
SECTION("array index get")
|
@@ -234,7 +251,7 @@ TEST_CASE("integration: subdoc get & exists", "[integration]")
|
|
234
251
|
|
235
252
|
SECTION("array index exists")
|
236
253
|
{
|
237
|
-
assert_single_lookup_success(integration, id, couchbase::lookup_in_specs::exists("array[0]"));
|
254
|
+
assert_single_lookup_success(integration, id, couchbase::lookup_in_specs::exists("array[0]"), "true");
|
238
255
|
}
|
239
256
|
|
240
257
|
SECTION("non existent path get")
|
@@ -252,7 +269,8 @@ TEST_CASE("integration: subdoc get & exists", "[integration]")
|
|
252
269
|
id,
|
253
270
|
couchbase::lookup_in_specs::exists("non-exist"),
|
254
271
|
couchbase::key_value_status_code::subdoc_path_not_found,
|
255
|
-
|
272
|
+
std::error_code{},
|
273
|
+
"false");
|
256
274
|
}
|
257
275
|
|
258
276
|
SECTION("non existent doc")
|
@@ -738,7 +756,7 @@ TEST_CASE("integration: subdoc multi lookup", "[integration]")
|
|
738
756
|
REQUIRE(resp.fields[0].value == couchbase::core::utils::to_binary(R"("dictval")"));
|
739
757
|
REQUIRE(resp.fields[0].status == couchbase::key_value_status_code::success);
|
740
758
|
|
741
|
-
REQUIRE(resp.fields[1].value
|
759
|
+
REQUIRE(resp.fields[1].value == couchbase::core::utils::to_binary("true"));
|
742
760
|
REQUIRE(resp.fields[1].status == couchbase::key_value_status_code::success);
|
743
761
|
REQUIRE(resp.fields[1].exists);
|
744
762
|
|
@@ -1082,7 +1100,7 @@ TEST_CASE("integration: subdoc all replica reads", "[integration]")
|
|
1082
1100
|
test::utils::integration_test_guard integration;
|
1083
1101
|
|
1084
1102
|
if (!integration.has_bucket_capability("subdoc.ReplicaRead")) {
|
1085
|
-
SKIP("
|
1103
|
+
SKIP("bucket does not support replica_read");
|
1086
1104
|
}
|
1087
1105
|
|
1088
1106
|
auto number_of_replicas = integration.number_of_replicas();
|
@@ -1114,7 +1132,7 @@ TEST_CASE("integration: subdoc all replica reads", "[integration]")
|
|
1114
1132
|
|
1115
1133
|
SECTION("dict exists")
|
1116
1134
|
{
|
1117
|
-
assert_single_lookup_all_replica_success(integration, id, couchbase::lookup_in_specs::exists("dictkey"));
|
1135
|
+
assert_single_lookup_all_replica_success(integration, id, couchbase::lookup_in_specs::exists("dictkey"), "true");
|
1118
1136
|
}
|
1119
1137
|
|
1120
1138
|
SECTION("array get")
|
@@ -1125,7 +1143,7 @@ TEST_CASE("integration: subdoc all replica reads", "[integration]")
|
|
1125
1143
|
|
1126
1144
|
SECTION("array exists")
|
1127
1145
|
{
|
1128
|
-
assert_single_lookup_all_replica_success(integration, id, couchbase::lookup_in_specs::exists("array"));
|
1146
|
+
assert_single_lookup_all_replica_success(integration, id, couchbase::lookup_in_specs::exists("array"), "true");
|
1129
1147
|
}
|
1130
1148
|
|
1131
1149
|
SECTION("array index get")
|
@@ -1135,7 +1153,7 @@ TEST_CASE("integration: subdoc all replica reads", "[integration]")
|
|
1135
1153
|
|
1136
1154
|
SECTION("array index exists")
|
1137
1155
|
{
|
1138
|
-
assert_single_lookup_all_replica_success(integration, id, couchbase::lookup_in_specs::exists("array[0]"));
|
1156
|
+
assert_single_lookup_all_replica_success(integration, id, couchbase::lookup_in_specs::exists("array[0]"), "true");
|
1139
1157
|
}
|
1140
1158
|
|
1141
1159
|
SECTION("non existent path get")
|
@@ -1153,7 +1171,8 @@ TEST_CASE("integration: subdoc all replica reads", "[integration]")
|
|
1153
1171
|
id,
|
1154
1172
|
couchbase::lookup_in_specs::exists("non-exist"),
|
1155
1173
|
couchbase::key_value_status_code::subdoc_path_not_found,
|
1156
|
-
|
1174
|
+
std::error_code{},
|
1175
|
+
"false");
|
1157
1176
|
}
|
1158
1177
|
|
1159
1178
|
SECTION("non existent doc")
|
@@ -1282,6 +1301,7 @@ TEST_CASE("integration: subdoc all replica reads", "[integration]")
|
|
1282
1301
|
REQUIRE(!res.cas().empty());
|
1283
1302
|
REQUIRE("dictval" == res.content_as<std::string>(0));
|
1284
1303
|
REQUIRE(res.exists("array"));
|
1304
|
+
REQUIRE(res.content_as<bool>(1));
|
1285
1305
|
REQUIRE(5 == res.content_as<int>(2));
|
1286
1306
|
}
|
1287
1307
|
}
|
@@ -1295,6 +1315,20 @@ TEST_CASE("integration: subdoc all replica reads", "[integration]")
|
|
1295
1315
|
REQUIRE(ctx.ec() == couchbase::errc::key_value::document_not_found);
|
1296
1316
|
REQUIRE(result.empty());
|
1297
1317
|
}
|
1318
|
+
|
1319
|
+
SECTION("non existent path exists")
|
1320
|
+
{
|
1321
|
+
auto specs = couchbase::lookup_in_specs{
|
1322
|
+
couchbase::lookup_in_specs::exists("non-exists"),
|
1323
|
+
};
|
1324
|
+
auto [ctx, result] = collection.lookup_in_all_replicas(key, specs).get();
|
1325
|
+
REQUIRE_SUCCESS(ctx.ec());
|
1326
|
+
for (auto& res : result) {
|
1327
|
+
REQUIRE(!res.cas().empty());
|
1328
|
+
REQUIRE(!res.exists(0));
|
1329
|
+
REQUIRE(!res.content_as<bool>(0));
|
1330
|
+
}
|
1331
|
+
}
|
1298
1332
|
}
|
1299
1333
|
}
|
1300
1334
|
|
@@ -1303,7 +1337,7 @@ TEST_CASE("integration: subdoc any replica reads", "[integration]")
|
|
1303
1337
|
test::utils::integration_test_guard integration;
|
1304
1338
|
|
1305
1339
|
if (!integration.has_bucket_capability("subdoc.ReplicaRead")) {
|
1306
|
-
SKIP("
|
1340
|
+
SKIP("bucket does not support replica_read");
|
1307
1341
|
}
|
1308
1342
|
|
1309
1343
|
auto number_of_replicas = integration.number_of_replicas();
|
@@ -1337,7 +1371,7 @@ TEST_CASE("integration: subdoc any replica reads", "[integration]")
|
|
1337
1371
|
|
1338
1372
|
SECTION("dict exists")
|
1339
1373
|
{
|
1340
|
-
assert_single_lookup_any_replica_success(integration, id, couchbase::lookup_in_specs::exists("dictkey"));
|
1374
|
+
assert_single_lookup_any_replica_success(integration, id, couchbase::lookup_in_specs::exists("dictkey"), "true");
|
1341
1375
|
}
|
1342
1376
|
|
1343
1377
|
SECTION("array get")
|
@@ -1348,7 +1382,7 @@ TEST_CASE("integration: subdoc any replica reads", "[integration]")
|
|
1348
1382
|
|
1349
1383
|
SECTION("array exists")
|
1350
1384
|
{
|
1351
|
-
assert_single_lookup_any_replica_success(integration, id, couchbase::lookup_in_specs::exists("array"));
|
1385
|
+
assert_single_lookup_any_replica_success(integration, id, couchbase::lookup_in_specs::exists("array"), "true");
|
1352
1386
|
}
|
1353
1387
|
|
1354
1388
|
SECTION("array index get")
|
@@ -1358,7 +1392,7 @@ TEST_CASE("integration: subdoc any replica reads", "[integration]")
|
|
1358
1392
|
|
1359
1393
|
SECTION("array index exists")
|
1360
1394
|
{
|
1361
|
-
assert_single_lookup_any_replica_success(integration, id, couchbase::lookup_in_specs::exists("array[0]"));
|
1395
|
+
assert_single_lookup_any_replica_success(integration, id, couchbase::lookup_in_specs::exists("array[0]"), "true");
|
1362
1396
|
}
|
1363
1397
|
|
1364
1398
|
SECTION("non existent path get")
|
@@ -1376,7 +1410,8 @@ TEST_CASE("integration: subdoc any replica reads", "[integration]")
|
|
1376
1410
|
id,
|
1377
1411
|
couchbase::lookup_in_specs::exists("non-exist"),
|
1378
1412
|
couchbase::key_value_status_code::subdoc_path_not_found,
|
1379
|
-
|
1413
|
+
std::error_code{},
|
1414
|
+
"false");
|
1380
1415
|
}
|
1381
1416
|
|
1382
1417
|
SECTION("non existent doc")
|
@@ -1516,6 +1551,7 @@ TEST_CASE("integration: subdoc any replica reads", "[integration]")
|
|
1516
1551
|
REQUIRE(!result.cas().empty());
|
1517
1552
|
REQUIRE("dictval" == result.content_as<std::string>(0));
|
1518
1553
|
REQUIRE(result.exists("array"));
|
1554
|
+
REQUIRE(result.content_as<bool>(1));
|
1519
1555
|
REQUIRE(5 == result.content_as<int>(2));
|
1520
1556
|
}
|
1521
1557
|
|
@@ -1540,6 +1576,17 @@ TEST_CASE("integration: subdoc any replica reads", "[integration]")
|
|
1540
1576
|
REQUIRE(ctx.ec() == couchbase::errc::common::invalid_argument);
|
1541
1577
|
REQUIRE(result.cas().empty());
|
1542
1578
|
}
|
1579
|
+
|
1580
|
+
SECTION("non existent path exists")
|
1581
|
+
{
|
1582
|
+
auto specs = couchbase::lookup_in_specs{
|
1583
|
+
couchbase::lookup_in_specs::exists("non-exists"),
|
1584
|
+
};
|
1585
|
+
auto [ctx, result] = collection.lookup_in_any_replica(key, specs).get();
|
1586
|
+
REQUIRE_SUCCESS(ctx.ec());
|
1587
|
+
REQUIRE(!result.exists(0));
|
1588
|
+
REQUIRE(!result.content_as<bool>(0));
|
1589
|
+
}
|
1543
1590
|
}
|
1544
1591
|
}
|
1545
1592
|
|
@@ -1627,4 +1674,16 @@ TEST_CASE("integration: public API lookup in per-spec errors", "[integration]")
|
|
1627
1674
|
}
|
1628
1675
|
REQUIRE_SUCCESS(ec);
|
1629
1676
|
}
|
1677
|
+
|
1678
|
+
SECTION("non existent path exists")
|
1679
|
+
{
|
1680
|
+
auto specs = couchbase::lookup_in_specs{
|
1681
|
+
couchbase::lookup_in_specs::exists("dictkey2"),
|
1682
|
+
};
|
1683
|
+
auto [ctx, result] = collection.lookup_in(key, specs).get();
|
1684
|
+
|
1685
|
+
REQUIRE_SUCCESS(ctx.ec());
|
1686
|
+
REQUIRE(!result.exists(0));
|
1687
|
+
REQUIRE(!result.content_as<bool>(0));
|
1688
|
+
}
|
1630
1689
|
}
|
data/ext/couchbase.cxx
CHANGED
@@ -1013,16 +1013,14 @@ cb_map_error_code(const couchbase::key_value_error_context& ctx, const std::stri
|
|
1013
1013
|
rb_hash_aset(enhanced_error_info, rb_id2sym(rb_intern("context")), cb_str_new(ctx.extended_error_info()->context()));
|
1014
1014
|
rb_hash_aset(error_context, rb_id2sym(rb_intern("extended_error_info")), enhanced_error_info);
|
1015
1015
|
}
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
rb_ary_push(retry_reasons, rb_id2sym(rb_intern(reason_str.c_str())));
|
1023
|
-
}
|
1024
|
-
rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_reasons")), retry_reasons);
|
1016
|
+
rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_attempts")), INT2FIX(ctx.retry_attempts()));
|
1017
|
+
if (!ctx.retry_reasons().empty()) {
|
1018
|
+
VALUE retry_reasons = rb_ary_new_capa(static_cast<long>(ctx.retry_reasons().size()));
|
1019
|
+
for (const auto& reason : ctx.retry_reasons()) {
|
1020
|
+
auto reason_str = fmt::format("{}", reason);
|
1021
|
+
rb_ary_push(retry_reasons, rb_id2sym(rb_intern(reason_str.c_str())));
|
1025
1022
|
}
|
1023
|
+
rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_reasons")), retry_reasons);
|
1026
1024
|
}
|
1027
1025
|
if (ctx.last_dispatched_to()) {
|
1028
1026
|
rb_hash_aset(error_context, rb_id2sym(rb_intern("last_dispatched_to")), cb_str_new(ctx.last_dispatched_to().value()));
|
@@ -3517,7 +3515,7 @@ cb_Backend_document_lookup_in(VALUE self, VALUE bucket, VALUE scope, VALUE colle
|
|
3517
3515
|
if (!resp_entry.value.empty()) {
|
3518
3516
|
rb_hash_aset(entry, value_property, cb_str_new(resp_entry.value));
|
3519
3517
|
}
|
3520
|
-
if (resp_entry.ec
|
3518
|
+
if (resp_entry.ec) {
|
3521
3519
|
rb_hash_aset(entry,
|
3522
3520
|
error_property,
|
3523
3521
|
cb_map_error_code(resp_entry.ec,
|
@@ -3628,7 +3626,7 @@ cb_Backend_document_lookup_in_any_replica(VALUE self, VALUE bucket, VALUE scope,
|
|
3628
3626
|
if (!resp_entry.value.empty()) {
|
3629
3627
|
rb_hash_aset(entry, value_property, cb_str_new(resp_entry.value));
|
3630
3628
|
}
|
3631
|
-
if (resp_entry.ec
|
3629
|
+
if (resp_entry.ec) {
|
3632
3630
|
rb_hash_aset(entry,
|
3633
3631
|
error_property,
|
3634
3632
|
cb_map_error_code(resp_entry.ec,
|
@@ -3744,7 +3742,7 @@ cb_Backend_document_lookup_in_all_replicas(VALUE self, VALUE bucket, VALUE scope
|
|
3744
3742
|
if (!field_entry.value.empty()) {
|
3745
3743
|
rb_hash_aset(entry, value_property, cb_str_new(field_entry.value));
|
3746
3744
|
}
|
3747
|
-
if (field_entry.ec
|
3745
|
+
if (field_entry.ec) {
|
3748
3746
|
rb_hash_aset(
|
3749
3747
|
entry,
|
3750
3748
|
error_property,
|
@@ -4370,18 +4368,20 @@ cb_Backend_document_query(VALUE self, VALUE statement, VALUE options)
|
|
4370
4368
|
static void
|
4371
4369
|
cb_generate_bucket_settings(VALUE bucket, couchbase::core::management::cluster::bucket_settings& entry, bool is_create)
|
4372
4370
|
{
|
4373
|
-
if (VALUE bucket_type = rb_hash_aref(bucket, rb_id2sym(rb_intern("bucket_type")));
|
4374
|
-
if (bucket_type
|
4375
|
-
|
4376
|
-
|
4377
|
-
|
4378
|
-
|
4379
|
-
|
4371
|
+
if (VALUE bucket_type = rb_hash_aref(bucket, rb_id2sym(rb_intern("bucket_type"))); !NIL_P(bucket_type)) {
|
4372
|
+
if (TYPE(bucket_type) == T_SYMBOL) {
|
4373
|
+
if (bucket_type == rb_id2sym(rb_intern("couchbase")) || bucket_type == rb_id2sym(rb_intern("membase"))) {
|
4374
|
+
entry.bucket_type = couchbase::core::management::cluster::bucket_type::couchbase;
|
4375
|
+
} else if (bucket_type == rb_id2sym(rb_intern("memcached"))) {
|
4376
|
+
entry.bucket_type = couchbase::core::management::cluster::bucket_type::memcached;
|
4377
|
+
} else if (bucket_type == rb_id2sym(rb_intern("ephemeral"))) {
|
4378
|
+
entry.bucket_type = couchbase::core::management::cluster::bucket_type::ephemeral;
|
4379
|
+
} else {
|
4380
|
+
throw ruby_exception(rb_eArgError, rb_sprintf("unknown bucket type, given %+" PRIsVALUE, bucket_type));
|
4381
|
+
}
|
4380
4382
|
} else {
|
4381
|
-
throw ruby_exception(rb_eArgError, rb_sprintf("
|
4383
|
+
throw ruby_exception(rb_eArgError, rb_sprintf("bucket type must be a Symbol, given %+" PRIsVALUE, bucket_type));
|
4382
4384
|
}
|
4383
|
-
} else {
|
4384
|
-
throw ruby_exception(rb_eArgError, rb_sprintf("bucket type must be a Symbol, given %+" PRIsVALUE, bucket_type));
|
4385
4385
|
}
|
4386
4386
|
|
4387
4387
|
if (VALUE name = rb_hash_aref(bucket, rb_id2sym(rb_intern("name"))); TYPE(name) == T_STRING) {
|
@@ -4390,10 +4390,12 @@ cb_generate_bucket_settings(VALUE bucket, couchbase::core::management::cluster::
|
|
4390
4390
|
throw ruby_exception(rb_eArgError, rb_sprintf("bucket name must be a String, given %+" PRIsVALUE, name));
|
4391
4391
|
}
|
4392
4392
|
|
4393
|
-
if (VALUE quota = rb_hash_aref(bucket, rb_id2sym(rb_intern("ram_quota_mb")));
|
4394
|
-
|
4395
|
-
|
4396
|
-
|
4393
|
+
if (VALUE quota = rb_hash_aref(bucket, rb_id2sym(rb_intern("ram_quota_mb"))); !NIL_P(quota)) {
|
4394
|
+
if (TYPE(quota) == T_FIXNUM) {
|
4395
|
+
entry.ram_quota_mb = FIX2ULONG(quota);
|
4396
|
+
} else {
|
4397
|
+
throw ruby_exception(rb_eArgError, rb_sprintf("bucket RAM quota must be an Integer, given %+" PRIsVALUE, quota));
|
4398
|
+
}
|
4397
4399
|
}
|
4398
4400
|
|
4399
4401
|
if (VALUE expiry = rb_hash_aref(bucket, rb_id2sym(rb_intern("max_expiry"))); !NIL_P(expiry)) {
|
@@ -4490,6 +4492,31 @@ cb_generate_bucket_settings(VALUE bucket, couchbase::core::management::cluster::
|
|
4490
4492
|
}
|
4491
4493
|
}
|
4492
4494
|
|
4495
|
+
if (VALUE history_retention_collection_default = rb_hash_aref(bucket, rb_id2sym(rb_intern("history_retention_collection_default")));
|
4496
|
+
!NIL_P(history_retention_collection_default)) {
|
4497
|
+
entry.history_retention_collection_default = RTEST(history_retention_collection_default);
|
4498
|
+
}
|
4499
|
+
|
4500
|
+
if (VALUE history_retention_bytes = rb_hash_aref(bucket, rb_id2sym(rb_intern("history_retention_bytes")));
|
4501
|
+
!NIL_P(history_retention_bytes)) {
|
4502
|
+
if (TYPE(history_retention_bytes) == T_FIXNUM) {
|
4503
|
+
entry.history_retention_bytes = FIX2UINT(history_retention_bytes);
|
4504
|
+
} else {
|
4505
|
+
throw ruby_exception(rb_eArgError,
|
4506
|
+
rb_sprintf("history retention bytes must be an Integer, given %+" PRIsVALUE, history_retention_bytes));
|
4507
|
+
}
|
4508
|
+
}
|
4509
|
+
|
4510
|
+
if (VALUE history_retention_duration = rb_hash_aref(bucket, rb_id2sym(rb_intern("history_retention_duration")));
|
4511
|
+
!NIL_P(history_retention_duration)) {
|
4512
|
+
if (TYPE(history_retention_duration) == T_FIXNUM) {
|
4513
|
+
entry.history_retention_duration = FIX2UINT(history_retention_duration);
|
4514
|
+
} else {
|
4515
|
+
throw ruby_exception(
|
4516
|
+
rb_eArgError, rb_sprintf("history retention duration must be an Integer, given %+" PRIsVALUE, history_retention_duration));
|
4517
|
+
}
|
4518
|
+
}
|
4519
|
+
|
4493
4520
|
if (is_create) {
|
4494
4521
|
if (VALUE conflict_resolution_type = rb_hash_aref(bucket, rb_id2sym(rb_intern("conflict_resolution_type")));
|
4495
4522
|
!NIL_P(conflict_resolution_type)) {
|
@@ -4654,7 +4681,9 @@ cb_extract_bucket_settings(const couchbase::core::management::cluster::bucket_se
|
|
4654
4681
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("name")), cb_str_new(entry.name));
|
4655
4682
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("uuid")), cb_str_new(entry.uuid));
|
4656
4683
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("ram_quota_mb")), ULL2NUM(entry.ram_quota_mb));
|
4657
|
-
|
4684
|
+
if (const auto& val = entry.max_expiry; val.has_value()) {
|
4685
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("max_expiry")), ULONG2NUM(val.value()));
|
4686
|
+
}
|
4658
4687
|
switch (entry.compression_mode) {
|
4659
4688
|
case couchbase::core::management::cluster::bucket_compression::off:
|
4660
4689
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("compression_mode")), rb_id2sym(rb_intern("off")));
|
@@ -4669,9 +4698,15 @@ cb_extract_bucket_settings(const couchbase::core::management::cluster::bucket_se
|
|
4669
4698
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("compression_mode")), Qnil);
|
4670
4699
|
break;
|
4671
4700
|
}
|
4672
|
-
|
4673
|
-
|
4674
|
-
|
4701
|
+
if (const auto& val = entry.num_replicas; val.has_value()) {
|
4702
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("num_replicas")), ULONG2NUM(val.value()));
|
4703
|
+
}
|
4704
|
+
if (const auto& val = entry.replica_indexes; val.has_value()) {
|
4705
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("replica_indexes")), val.value() ? Qtrue : Qfalse);
|
4706
|
+
}
|
4707
|
+
if (const auto& val = entry.flush_enabled; val.has_value()) {
|
4708
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("flush_enabled")), val.value() ? Qtrue : Qfalse);
|
4709
|
+
}
|
4675
4710
|
switch (entry.eviction_policy) {
|
4676
4711
|
case couchbase::core::management::cluster::bucket_eviction_policy::full:
|
4677
4712
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("eviction_policy")), rb_id2sym(rb_intern("full")));
|
@@ -4720,6 +4755,18 @@ cb_extract_bucket_settings(const couchbase::core::management::cluster::bucket_se
|
|
4720
4755
|
break;
|
4721
4756
|
}
|
4722
4757
|
}
|
4758
|
+
if (entry.history_retention_collection_default.has_value()) {
|
4759
|
+
rb_hash_aset(bucket,
|
4760
|
+
rb_id2sym(rb_intern("history_retention_collection_default")),
|
4761
|
+
entry.history_retention_collection_default.value() ? Qtrue : Qfalse);
|
4762
|
+
}
|
4763
|
+
if (const auto& val = entry.history_retention_bytes; val.has_value()) {
|
4764
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("history_retention_bytes")), ULONG2NUM(val.value()));
|
4765
|
+
}
|
4766
|
+
if (const auto& val = entry.history_retention_duration; val.has_value()) {
|
4767
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("history_retention_duration")), ULONG2NUM(val.value()));
|
4768
|
+
}
|
4769
|
+
|
4723
4770
|
VALUE capabilities = rb_ary_new_capa(static_cast<long>(entry.capabilities.size()));
|
4724
4771
|
for (const auto& capa : entry.capabilities) {
|
4725
4772
|
rb_ary_push(capabilities, cb_str_new(capa));
|
@@ -5401,6 +5448,10 @@ cb_Backend_scope_get_all(VALUE self, VALUE bucket_name, VALUE options)
|
|
5401
5448
|
VALUE collection = rb_hash_new();
|
5402
5449
|
rb_hash_aset(collection, rb_id2sym(rb_intern("uid")), ULL2NUM(c.uid));
|
5403
5450
|
rb_hash_aset(collection, rb_id2sym(rb_intern("name")), cb_str_new(c.name));
|
5451
|
+
rb_hash_aset(collection, rb_id2sym(rb_intern("max_expiry")), ULONG2NUM(c.max_expiry));
|
5452
|
+
if (c.history.has_value()) {
|
5453
|
+
rb_hash_aset(collection, rb_id2sym(rb_intern("history")), c.history.value() ? Qtrue : Qfalse);
|
5454
|
+
}
|
5404
5455
|
rb_ary_push(collections, collection);
|
5405
5456
|
}
|
5406
5457
|
rb_hash_aset(scope, rb_id2sym(rb_intern("collections")), collections);
|
@@ -5531,13 +5582,16 @@ cb_Backend_scope_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE opt
|
|
5531
5582
|
}
|
5532
5583
|
|
5533
5584
|
static VALUE
|
5534
|
-
cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE
|
5585
|
+
cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE settings, VALUE options)
|
5535
5586
|
{
|
5536
5587
|
const auto& cluster = cb_backend_to_cluster(self);
|
5537
5588
|
|
5538
5589
|
Check_Type(bucket_name, T_STRING);
|
5539
5590
|
Check_Type(scope_name, T_STRING);
|
5540
5591
|
Check_Type(collection_name, T_STRING);
|
5592
|
+
if (!NIL_P(settings)) {
|
5593
|
+
Check_Type(settings, T_HASH);
|
5594
|
+
}
|
5541
5595
|
if (!NIL_P(options)) {
|
5542
5596
|
Check_Type(options, T_HASH);
|
5543
5597
|
}
|
@@ -5548,10 +5602,20 @@ cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VA
|
|
5548
5602
|
cb_string_new(collection_name) };
|
5549
5603
|
cb_extract_timeout(req, options);
|
5550
5604
|
|
5551
|
-
if (!NIL_P(
|
5552
|
-
|
5553
|
-
|
5605
|
+
if (!NIL_P(settings)) {
|
5606
|
+
if (VALUE max_expiry = rb_hash_aref(settings, rb_id2sym(rb_intern("max_expiry"))); !NIL_P(max_expiry)) {
|
5607
|
+
if (TYPE(max_expiry) == T_FIXNUM) {
|
5608
|
+
req.max_expiry = FIX2UINT(max_expiry);
|
5609
|
+
} else {
|
5610
|
+
throw ruby_exception(rb_eArgError,
|
5611
|
+
rb_sprintf("collection max expiry must be an Integer, given %+" PRIsVALUE, max_expiry));
|
5612
|
+
}
|
5613
|
+
}
|
5614
|
+
if (VALUE history = rb_hash_aref(settings, rb_id2sym(rb_intern("history"))); !NIL_P(history)) {
|
5615
|
+
req.history = RTEST(history);
|
5616
|
+
}
|
5554
5617
|
}
|
5618
|
+
|
5555
5619
|
auto barrier = std::make_shared<std::promise<couchbase::core::operations::management::collection_create_response>>();
|
5556
5620
|
auto f = barrier->get_future();
|
5557
5621
|
cluster->execute(req, [barrier](couchbase::core::operations::management::collection_create_response&& resp) {
|
@@ -5573,6 +5637,62 @@ cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VA
|
|
5573
5637
|
return Qnil;
|
5574
5638
|
}
|
5575
5639
|
|
5640
|
+
static VALUE
|
5641
|
+
cb_Backend_collection_update(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE settings, VALUE options)
|
5642
|
+
{
|
5643
|
+
const auto& cluster = cb_backend_to_cluster(self);
|
5644
|
+
|
5645
|
+
Check_Type(bucket_name, T_STRING);
|
5646
|
+
Check_Type(scope_name, T_STRING);
|
5647
|
+
Check_Type(collection_name, T_STRING);
|
5648
|
+
if (!NIL_P(settings)) {
|
5649
|
+
Check_Type(settings, T_HASH);
|
5650
|
+
}
|
5651
|
+
if (!NIL_P(options)) {
|
5652
|
+
Check_Type(options, T_HASH);
|
5653
|
+
}
|
5654
|
+
|
5655
|
+
try {
|
5656
|
+
couchbase::core::operations::management::collection_update_request req{ cb_string_new(bucket_name),
|
5657
|
+
cb_string_new(scope_name),
|
5658
|
+
cb_string_new(collection_name) };
|
5659
|
+
cb_extract_timeout(req, options);
|
5660
|
+
|
5661
|
+
if (!NIL_P(settings)) {
|
5662
|
+
if (VALUE max_expiry = rb_hash_aref(settings, rb_id2sym(rb_intern("max_expiry"))); !NIL_P(max_expiry)) {
|
5663
|
+
if (TYPE(max_expiry) == T_FIXNUM) {
|
5664
|
+
req.max_expiry = FIX2UINT(max_expiry);
|
5665
|
+
} else {
|
5666
|
+
throw ruby_exception(rb_eArgError,
|
5667
|
+
rb_sprintf("collection max expiry must be an Integer, given %+" PRIsVALUE, max_expiry));
|
5668
|
+
}
|
5669
|
+
}
|
5670
|
+
if (VALUE history = rb_hash_aref(settings, rb_id2sym(rb_intern("history"))); !NIL_P(history)) {
|
5671
|
+
req.history = RTEST(history);
|
5672
|
+
}
|
5673
|
+
}
|
5674
|
+
|
5675
|
+
auto barrier = std::make_shared<std::promise<couchbase::core::operations::management::collection_update_response>>();
|
5676
|
+
auto f = barrier->get_future();
|
5677
|
+
cluster->execute(req, [barrier](couchbase::core::operations::management::collection_update_response&& resp) {
|
5678
|
+
barrier->set_value(std::move(resp));
|
5679
|
+
});
|
5680
|
+
auto resp = cb_wait_for_future(f);
|
5681
|
+
if (resp.ctx.ec) {
|
5682
|
+
cb_throw_error_code(
|
5683
|
+
resp.ctx,
|
5684
|
+
fmt::format(
|
5685
|
+
R"(unable update the collection "{}.{}" on the bucket "{}")", req.scope_name, req.collection_name, req.bucket_name));
|
5686
|
+
}
|
5687
|
+
return ULL2NUM(resp.uid);
|
5688
|
+
} catch (const std::system_error& se) {
|
5689
|
+
rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
|
5690
|
+
} catch (const ruby_exception& e) {
|
5691
|
+
rb_exc_raise(e.exception_object());
|
5692
|
+
}
|
5693
|
+
return Qnil;
|
5694
|
+
}
|
5695
|
+
|
5576
5696
|
static VALUE
|
5577
5697
|
cb_Backend_collection_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE options)
|
5578
5698
|
{
|
@@ -9190,6 +9310,7 @@ init_backend(VALUE mCouchbase)
|
|
9190
9310
|
rb_define_method(cBackend, "scope_create", VALUE_FUNC(cb_Backend_scope_create), 3);
|
9191
9311
|
rb_define_method(cBackend, "scope_drop", VALUE_FUNC(cb_Backend_scope_drop), 3);
|
9192
9312
|
rb_define_method(cBackend, "collection_create", VALUE_FUNC(cb_Backend_collection_create), 5);
|
9313
|
+
rb_define_method(cBackend, "collection_update", VALUE_FUNC(cb_Backend_collection_update), 5);
|
9193
9314
|
rb_define_method(cBackend, "collection_drop", VALUE_FUNC(cb_Backend_collection_drop), 4);
|
9194
9315
|
|
9195
9316
|
rb_define_method(cBackend, "query_index_get_all", VALUE_FUNC(cb_Backend_query_index_get_all), 2);
|
data/ext/revisions.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
cmake_flags << "-DEXT_GIT_REVISION=
|
2
|
-
cmake_flags << "-DCOUCHBASE_CXX_CLIENT_GIT_REVISION=
|
3
|
-
cmake_flags << "-DCOUCHBASE_CXX_CLIENT_GIT_DESCRIBE=1.0.0-dp.
|
1
|
+
cmake_flags << "-DEXT_GIT_REVISION=276c680f5d7d8c33d270470f473a42a9d91c11c7"
|
2
|
+
cmake_flags << "-DCOUCHBASE_CXX_CLIENT_GIT_REVISION=a873bb91aa487fab8acd3b619355b911b1588fc1"
|
3
|
+
cmake_flags << "-DCOUCHBASE_CXX_CLIENT_GIT_DESCRIBE=1.0.0-dp.9-0-ga873bb9"
|
@@ -169,7 +169,6 @@ module Couchbase
|
|
169
169
|
field = get_field_at_index(path_or_index)
|
170
170
|
|
171
171
|
raise field.error unless field.error.nil?
|
172
|
-
raise Error::PathNotFound, "Path is not found: #{path_or_index}" unless field.exists
|
173
172
|
|
174
173
|
transcoder.decode(field.value, :json)
|
175
174
|
end
|
@@ -191,7 +190,7 @@ module Couchbase
|
|
191
190
|
end
|
192
191
|
return false unless field
|
193
192
|
|
194
|
-
raise field.error unless field.error.nil?
|
193
|
+
raise field.error unless field.error.nil? || field.error.is_a?(Error::PathNotFound)
|
195
194
|
|
196
195
|
field.exists
|
197
196
|
end
|