@@ -384,11 +384,11 @@ void HttpServer::DoHandleRun(const httplib::Request &req,
384384 }
385385
386386 // default to effectively no limit
387- auto result_chunk_limit = INT_MAX;
388- auto result_chunk_limit_string =
389- req.get_header_value (" X-DuckDB-UI-Result-Chunk -Limit" );
390- if (!result_chunk_limit_string .empty ()) {
391- result_chunk_limit = std::stoi (result_chunk_limit_string );
387+ auto result_row_limit = INT_MAX;
388+ auto result_row_limit_string =
389+ req.get_header_value (" X-DuckDB-UI-Result-Row -Limit" );
390+ if (!result_row_limit_string .empty ()) {
391+ result_row_limit = std::stoi (result_row_limit_string );
392392 }
393393
394394 auto result_database_name_option =
@@ -398,14 +398,14 @@ void HttpServer::DoHandleRun(const httplib::Request &req,
398398 auto result_table_name =
399399 DecodeBase64 (req.get_header_value (" X-DuckDB-UI-Result-Table-Name" ));
400400
401- // If no result table is specified, then the result table chunk limit is zero.
401+ // If no result table is specified, then the result table row limit is zero.
402402 // Otherwise, default to effectively no limit.
403- auto result_table_chunk_limit = result_table_name.empty () ? 0 : INT_MAX;
404- auto result_table_chunk_limit_string =
405- req.get_header_value (" X-DuckDB-UI-Result-Table-Chunk -Limit" );
406- // Only set the result table chunk limit if a result table name is specified.
407- if (!result_table_name.empty () && !result_table_chunk_limit_string .empty ()) {
408- result_table_chunk_limit = std::stoi (result_table_chunk_limit_string );
403+ auto result_table_row_limit = result_table_name.empty () ? 0 : INT_MAX;
404+ auto result_table_row_limit_string =
405+ req.get_header_value (" X-DuckDB-UI-Result-Table-Row -Limit" );
406+ // Only set the result table row limit if a result table name is specified.
407+ if (!result_table_name.empty () && !result_table_row_limit_string .empty ()) {
408+ result_table_row_limit = std::stoi (result_table_row_limit_string );
409409 }
410410
411411 auto errors_as_json_string =
@@ -588,21 +588,39 @@ void HttpServer::DoHandleRun(const httplib::Request &req,
588588 success_result.column_names_and_types = {std::move (result->names ),
589589 std::move (result->types )};
590590
591- auto chunk_limit = std::max (result_chunk_limit, result_table_chunk_limit);
592- auto chunks_fetched = 0 ;
591+ auto row_limit = std::max (result_row_limit, result_table_row_limit);
592+ auto rows_fetched = 0 ;
593+ auto rows_appended = 0 ;
594+ auto rows_in_result = 0 ;
593595 unique_ptr<duckdb::DataChunk> chunk;
594- while (chunks_fetched < chunk_limit ) {
596+ while (rows_fetched < row_limit ) {
595597 chunk = result->Fetch ();
596598 if (!chunk) {
597599 break ;
598600 }
599- ++chunks_fetched;
600- if (appender && chunks_fetched <= result_table_chunk_limit) {
601- appender->AppendDataChunk (*chunk);
601+ rows_fetched += chunk->size ();
602+ if (appender && rows_appended < result_table_row_limit) {
603+ duckdb::DataChunk *chunk_to_append = chunk.get ();
604+ duckdb::DataChunk chunk_prefix;
605+ auto rows_left = result_table_row_limit - rows_appended;
606+ if (chunk->size () > rows_left) {
607+ HttpServer::CopyAndSlice (*chunk, chunk_prefix, rows_left);
608+ chunk_to_append = &chunk_prefix;
609+ }
610+ appender->AppendDataChunk (*chunk_to_append);
611+ rows_appended += chunk_to_append->size ();
602612 }
603- if (chunks_fetched <= result_chunk_limit) {
613+ if (rows_in_result < result_row_limit) {
614+ duckdb::DataChunk *chunk_to_add = chunk.get ();
615+ duckdb::DataChunk chunk_prefix;
616+ auto rows_left = result_row_limit - rows_in_result;
617+ if (chunk->size () > rows_left) {
618+ HttpServer::CopyAndSlice (*chunk, chunk_prefix, rows_left);
619+ chunk_to_add = &chunk_prefix;
620+ }
604621 success_result.chunks .push_back (
605- {static_cast <uint16_t >(chunk->size ()), std::move (chunk->data )});
622+ {static_cast <uint16_t >(chunk_to_add->size ()), std::move (chunk_to_add->data )});
623+ rows_in_result += chunk_to_add->size ();
606624 }
607625 }
608626
@@ -687,5 +705,11 @@ void HttpServer::SetResponseErrorResult(httplib::Response &res,
687705 SetResponseContent (res, response_content);
688706}
689707
708+ void HttpServer::CopyAndSlice (duckdb::DataChunk &source, duckdb::DataChunk &target, idx_t row_count) {
709+ target.InitializeEmpty (source.GetTypes ());
710+ target.Reference (source);
711+ target.Slice (0 , row_count);
712+ }
713+
690714} // namespace ui
691715} // namespace duckdb
0 commit comments