Skip to content

Commit 3d7ae18

Browse files
authored
change chunk limit to row limit (#25)
* change chunk limit to row limit * save or return no more than row limit * factor out slice & copy code
1 parent e0047d5 commit 3d7ae18

File tree

4 files changed

+55
-29
lines changed

4 files changed

+55
-29
lines changed

src/http_server.cpp

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

src/include/http_server.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class HttpServer {
7272
shared_ptr<DatabaseInstance> LockDatabaseInstance();
7373
void InitClientFromParams(httplib::Client &);
7474

75+
static void CopyAndSlice(duckdb::DataChunk &source, duckdb::DataChunk &target, idx_t row_count);
76+
7577
uint16_t local_port;
7678
std::string local_url;
7779
std::string remote_url;

ts/pkgs/duckdb-ui-client/src/client/types/DuckDBUIRunOptions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ export interface DuckDBUIRunOptions {
44
schemaName?: string;
55
errorsAsJson?: boolean;
66
parameters?: unknown[];
7-
resultChunkLimit?: number;
7+
resultRowLimit?: number;
88
resultDatabaseName?: string;
99
resultSchemaName?: string;
1010
resultTableName?: string;
11-
resultTableChunkLimit?: number;
11+
resultTableRowLimit?: number;
1212
}

ts/pkgs/duckdb-ui-client/src/http/functions/makeDuckDBUIHttpRequestHeaders.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ export function makeDuckDBUIHttpRequestHeaders({
1212
schemaName,
1313
errorsAsJson,
1414
parameters,
15-
resultChunkLimit,
15+
resultRowLimit,
1616
resultDatabaseName,
1717
resultSchemaName,
1818
resultTableName,
19-
resultTableChunkLimit,
19+
resultTableRowLimit,
2020
}: DuckDBUIHttpRequestHeaderOptions): Headers {
2121
const headers = new Headers();
2222
// We base64 encode some values because they can contain characters invalid in an HTTP header.
@@ -42,8 +42,8 @@ export function makeDuckDBUIHttpRequestHeaders({
4242
);
4343
}
4444
}
45-
if (resultChunkLimit !== undefined) {
46-
headers.append('X-DuckDB-UI-Result-Chunk-Limit', String(resultChunkLimit));
45+
if (resultRowLimit !== undefined) {
46+
headers.append('X-DuckDB-UI-Result-Row-Limit', String(resultRowLimit));
4747
}
4848
if (resultDatabaseName) {
4949
headers.append(
@@ -60,10 +60,10 @@ export function makeDuckDBUIHttpRequestHeaders({
6060
if (resultTableName) {
6161
headers.append('X-DuckDB-UI-Result-Table-Name', toBase64(resultTableName));
6262
}
63-
if (resultTableChunkLimit !== undefined) {
63+
if (resultTableRowLimit !== undefined) {
6464
headers.append(
65-
'X-DuckDB-UI-Result-Table-Chunk-Limit',
66-
String(resultTableChunkLimit),
65+
'X-DuckDB-UI-Result-Table-Row-Limit',
66+
String(resultTableRowLimit),
6767
);
6868
}
6969
if (errorsAsJson) {

0 commit comments

Comments
 (0)