Skip to content

Commit 43cf66a

Browse files
authored
Expose spec-specific errors in the public API for lookup in (#443)
1 parent c6be14e commit 43cf66a

File tree

3 files changed

+113
-0
lines changed

3 files changed

+113
-0
lines changed

core/impl/lookup_in.cxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ initiate_lookup_in_operation(std::shared_ptr<couchbase::core::cluster> core,
6060
std::move(entry.value),
6161
entry.original_index,
6262
entry.exists,
63+
entry.ec,
6364
});
6465
}
6566
return handler(std::move(resp.ctx), lookup_in_result{ resp.cas, std::move(entries), resp.deleted });

couchbase/lookup_in_result.hxx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class lookup_in_result : public result
4444
codec::binary value;
4545
std::size_t original_index;
4646
bool exists;
47+
std::error_code ec;
4748
};
4849

4950
/**
@@ -84,6 +85,11 @@ class lookup_in_result : public result
8485
{
8586
for (const entry& e : entries_) {
8687
if (e.original_index == index) {
88+
if (e.ec) {
89+
throw std::system_error(
90+
e.ec, "error getting result for spec at index " + std::to_string(index) + ", path \"" + e.path + "\"");
91+
}
92+
8793
return codec::tao_json_serializer::deserialize<Document>(e.value);
8894
}
8995
}
@@ -105,6 +111,10 @@ class lookup_in_result : public result
105111
{
106112
for (const entry& e : entries_) {
107113
if (e.path == path) {
114+
if (e.ec) {
115+
throw std::system_error(e.ec, "error getting result for path \"" + e.path + "\"");
116+
}
117+
108118
return codec::tao_json_serializer::deserialize<Document>(e.value);
109119
}
110120
}
@@ -127,6 +137,10 @@ class lookup_in_result : public result
127137
const auto& macro_string = subdoc::to_string(macro);
128138
for (const entry& e : entries_) {
129139
if (e.path == macro_string) {
140+
if (e.ec) {
141+
throw std::system_error(e.ec, "error getting result for macro \"" + macro_string + "\"");
142+
}
143+
130144
return codec::tao_json_serializer::deserialize<Document>(e.value);
131145
}
132146
}
@@ -147,6 +161,10 @@ class lookup_in_result : public result
147161
{
148162
for (const entry& e : entries_) {
149163
if (e.original_index == index) {
164+
if (e.ec && e.ec != couchbase::errc::key_value::path_not_found) {
165+
throw std::system_error(e.ec, "error getting result for path \"" + e.path + "\"");
166+
}
167+
150168
return e.exists;
151169
}
152170
}
@@ -167,6 +185,10 @@ class lookup_in_result : public result
167185
const auto& macro_string = subdoc::to_string(macro);
168186
for (const entry& e : entries_) {
169187
if (e.path == macro_string) {
188+
if (e.ec && e.ec != couchbase::errc::key_value::path_not_found) {
189+
throw std::system_error(e.ec, "error getting result for macro \"" + macro_string + "\"");
190+
}
191+
170192
return e.exists;
171193
}
172194
}
@@ -186,6 +208,10 @@ class lookup_in_result : public result
186208
{
187209
for (const entry& e : entries_) {
188210
if (e.path == path) {
211+
if (e.ec && e.ec != couchbase::errc::key_value::path_not_found) {
212+
throw std::system_error(e.ec, "error getting result for path \"" + e.path + "\"");
213+
}
214+
189215
return e.exists;
190216
}
191217
}

test/test_integration_subdoc.cxx

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,3 +1542,89 @@ TEST_CASE("integration: subdoc any replica reads", "[integration]")
15421542
}
15431543
}
15441544
}
1545+
1546+
TEST_CASE("integration: public API lookup in per-spec errors", "[integration]")
1547+
{
1548+
test::utils::integration_test_guard integration;
1549+
1550+
auto collection = couchbase::cluster(integration.cluster).bucket(integration.ctx.bucket).scope("_default").collection("_default");
1551+
1552+
auto key = test::utils::uniq_id("lookup_in_path_invalid");
1553+
{
1554+
auto value_json = couchbase::core::utils::json::parse(R"({"dictkey":"dictval","array":[1,2,3,4,[10,20,30,[100,200,300]]]})");
1555+
auto [ctx, result] = collection.upsert(key, value_json).get();
1556+
REQUIRE_SUCCESS(ctx.ec());
1557+
}
1558+
1559+
SECTION("path invalid")
1560+
{
1561+
auto specs = couchbase::lookup_in_specs{
1562+
couchbase::lookup_in_specs::get("..dictkey"),
1563+
};
1564+
auto [ctx, result] = collection.lookup_in(key, specs).get();
1565+
std::error_code ec{};
1566+
try {
1567+
std::ignore = result.content_as<std::string>(0);
1568+
} catch (std::system_error& exc) {
1569+
ec = exc.code();
1570+
}
1571+
REQUIRE(ec == couchbase::errc::key_value::path_invalid);
1572+
1573+
ec.clear();
1574+
try {
1575+
std::ignore = result.exists(0);
1576+
} catch (std::system_error& exc) {
1577+
ec = exc.code();
1578+
}
1579+
REQUIRE(ec == couchbase::errc::key_value::path_invalid);
1580+
}
1581+
1582+
SECTION("path mismatch")
1583+
{
1584+
auto specs = couchbase::lookup_in_specs{
1585+
couchbase::lookup_in_specs::count("dictkey"),
1586+
};
1587+
auto [ctx, result] = collection.lookup_in(key, specs).get();
1588+
1589+
std::error_code ec{};
1590+
try {
1591+
std::ignore = result.content_as<std::string>(0);
1592+
} catch (std::system_error& exc) {
1593+
ec = exc.code();
1594+
}
1595+
REQUIRE(ec == couchbase::errc::key_value::path_mismatch);
1596+
1597+
ec.clear();
1598+
try {
1599+
std::ignore = result.exists(0);
1600+
} catch (std::system_error& exc) {
1601+
ec = exc.code();
1602+
}
1603+
REQUIRE(ec == couchbase::errc::key_value::path_mismatch);
1604+
}
1605+
1606+
SECTION("path not found")
1607+
{
1608+
auto specs = couchbase::lookup_in_specs{
1609+
couchbase::lookup_in_specs::get("dictkey2"),
1610+
};
1611+
auto [ctx, result] = collection.lookup_in(key, specs).get();
1612+
1613+
std::error_code ec{};
1614+
try {
1615+
std::ignore = result.content_as<std::string>(0);
1616+
} catch (std::system_error& exc) {
1617+
ec = exc.code();
1618+
}
1619+
REQUIRE(ec == couchbase::errc::key_value::path_not_found);
1620+
1621+
ec.clear();
1622+
try {
1623+
auto exists = result.exists(0);
1624+
REQUIRE_FALSE(exists);
1625+
} catch (std::system_error& exc) {
1626+
ec = exc.code();
1627+
}
1628+
REQUIRE_SUCCESS(ec);
1629+
}
1630+
}

0 commit comments

Comments
 (0)