Skip to content

Commit 89d1591

Browse files
committed
CXXCBC-173: complete streaming lexer even if pointer didn't match
1 parent f1e1abf commit 89d1591

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

couchbase/utils/json_streaming_lexer.cxx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ row_pop_callback(jsonsl_t lexer, jsonsl_action_t /* action */, struct jsonsl_sta
310310
}
311311

312312
static void
313-
initial_action_pop_callback(jsonsl_t lexer, jsonsl_action_t /* action */, struct jsonsl_state_st* state, const jsonsl_char_t* /* at */)
313+
initial_action_pop_callback(jsonsl_t lexer, jsonsl_action_t action, struct jsonsl_state_st* state, const jsonsl_char_t* at)
314314
{
315315
auto* impl = static_cast<detail::streaming_lexer_impl*>(lexer->data);
316316

@@ -321,6 +321,10 @@ initial_action_pop_callback(jsonsl_t lexer, jsonsl_action_t /* action */, struct
321321
if (state->type == JSONSL_T_HKEY) {
322322
impl->last_key_ = impl->buffer_.substr(state->pos_begin + 1, state->pos_cur - state->pos_begin - 1);
323323
}
324+
325+
if (state->data == STATE_MARKER_ROOT) {
326+
trailer_pop_callback(lexer, action, state, at);
327+
}
324328
}
325329

326330
static void

test/test_integration_query.cxx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,3 +405,25 @@ TEST_CASE("integration: sticking query to the service node", "[integration]")
405405
REQUIRE(std::set(used_nodes.begin(), used_nodes.end()).size() == 1);
406406
}
407407
}
408+
409+
TEST_CASE("analytics create dataset")
410+
{
411+
test::utils::integration_test_guard integration;
412+
413+
if (!integration.cluster_version().supports_analytics() || !integration.has_analytics_service() ||
414+
!integration.cluster_version().supports_collections()) {
415+
return;
416+
}
417+
if (!integration.cluster_version().supports_gcccp()) {
418+
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
419+
}
420+
couchbase::operations::analytics_request req{ fmt::format("CREATE DATAVERSE `{}`.`test-scope` IF NOT EXISTS", integration.ctx.bucket) };
421+
std::vector<std::string> rows{};
422+
req.row_callback = [&rows](std::string&& row) {
423+
rows.emplace_back(std::move(row));
424+
return couchbase::utils::json::stream_control::next_row;
425+
};
426+
427+
auto resp = test::utils::execute(integration.cluster, req);
428+
REQUIRE_FALSE(resp.ctx.ec);
429+
}

test/test_unit_json_streaming_lexer.cxx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,50 @@ TEST_CASE("unit: json_streaming_lexer parse chunked metadata trailer", "[unit]")
185185
REQUIRE(result.meta == expected_meta);
186186
REQUIRE(result.rows[0] == R"(42)");
187187
}
188+
189+
TEST_CASE("unit: json_streaming_lexer parse payload with missing results", "[unit]")
190+
{
191+
test::utils::init_logger();
192+
193+
std::string chunk = R"(
194+
{
195+
196+
"requestID": "d07c0cde-cd80-4620-bb6b-d0641f272420",
197+
"clientContextID": "a7bbe750-20a2-4e46-eb67-315e3733b2a8",
198+
"signature": {
199+
"*": "*"
200+
},
201+
"plans":{},
202+
"status": "success",
203+
"metrics": {
204+
"elapsedTime": "6.56579ms",
205+
"executionTime": "5.552905ms",
206+
"resultCount": 0,
207+
"resultSize": 0,
208+
"processedObjects": 0
209+
}
210+
}
211+
)";
212+
couchbase::utils::json::streaming_lexer lexer("/results/^", 4);
213+
query_result result{};
214+
bool on_row_handler_executed = false;
215+
lexer.on_row([&result, &on_row_handler_executed](std::string&& row) {
216+
on_row_handler_executed = true;
217+
result.rows.emplace_back(std::move(row));
218+
return couchbase::utils::json::stream_control::next_row;
219+
});
220+
bool on_complete_handler_excecuted = false;
221+
lexer.on_complete([&result, &on_complete_handler_excecuted](std::error_code ec, std::size_t number_of_rows, std::string&& meta) {
222+
on_complete_handler_excecuted = true;
223+
result.ec = ec;
224+
result.number_of_rows = number_of_rows;
225+
result.meta = std::move(meta);
226+
});
227+
lexer.feed(chunk);
228+
REQUIRE_FALSE(on_row_handler_executed);
229+
REQUIRE(on_complete_handler_excecuted);
230+
REQUIRE_FALSE(result.ec);
231+
REQUIRE(result.number_of_rows == 0);
232+
REQUIRE(result.rows.empty());
233+
REQUIRE(result.meta == chunk);
234+
}

0 commit comments

Comments
 (0)