Skip to content

fix: return empty DataSet instead of EmptyData for zero-row queries#38

Open
maltesander wants to merge 1 commit into
nudibranches-tech:mainfrom
maltesander:fix/get-all-empty-result-set
Open

fix: return empty DataSet instead of EmptyData for zero-row queries#38
maltesander wants to merge 1 commit into
nudibranches-tech:mainfrom
maltesander:fix/get-all-empty-result-set

Conversation

@maltesander
Copy link
Copy Markdown

Hi all, i stumbled over a possible bug in the getData() call.

Problem

In client.rs get_all(), the first response from Trino is almost always in QUEUED or PLANNING state with data: null, routing execution into the None arm of the match. The code then polls subsequent pages, accumulating rows. When the query produces no rows, the page loop ends with an empty accumulator and the following code was reached:

// src/client.rs (before fix)
  if !all_rows.is_empty() {
      build_dataset(all_rows, columns)
  } else {
      Err(Error::EmptyData)   // incorrect: valid query, just zero rows
  }

Err(EmptyData) is the wrong outcome here in my opinion. An empty result set is not an error, it is a valid query result with a known schema and zero rows.

Fix

Replace the guard with an unconditional build_dataset call. build_dataset already handles an empty Vec<T> correctly for both dynamic Row and derived #[derive(Trino)] types:

// src/client.rs (after fix)
#[cfg(feature = "spooling")]
if let Some(ds) = dataset {
  Ok(ds)
} else {
  build_dataset(all_rows, columns)
}
#[cfg(not(feature = "spooling"))]
build_dataset(all_rows, columns)

Test

I let Claude add two tests for this problem, but i am unsure if that really fits the test pattern here. It uses the "MockServer" and async calls to verify the fix.

tests/get_all_empty.rs adds two #[tokio::test] cases backed by a wiremock server simulating the real Trino two-page lifecycle (QUEUED → FINISHED with columns, no data):

  • test_get_all_empty_result_set_row_type — exercises the TrinoTy::Unknown / Row code path in build_dataset

  • test_get_all_empty_result_set_derived_type — exercises the DataSet::new / T::ty() path for a #[derive(Trino)] struct

    The page-2 fixture reuses tests/data/models/query_result_empty (already present in the repo).

cargo test --test get_all_empty

Feedback on how to improve/adapt that would be appreciated.

get_all() was returning Err(EmptyData) when a query completed with
valid column metadata but zero rows (e.g. WHERE 1=0). Replace the
empty-check guard with an unconditional build_dataset() call, which
already handles empty Vec<T> correctly.

Add tests/get_all_empty.rs to cover both Row and derived Trino struct
types using a wiremock server simulating the QUEUED → FINISHED flow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant