()
| 286 | /// ROLLUP adds (country) and () set variants. |
| 287 | #[tokio::test(flavor = "multi_thread", worker_threads = 4)] |
| 288 | async fn mixed_plain_and_rollup() { |
| 289 | let server = TestServer::start().await; |
| 290 | create_orders(&server).await; |
| 291 | |
| 292 | let rows = server |
| 293 | .query_rows( |
| 294 | "SELECT region, country, SUM(sales) AS total \ |
| 295 | FROM orders \ |
| 296 | GROUP BY region, ROLLUP (country)", |
| 297 | ) |
| 298 | .await |
| 299 | .unwrap(); |
| 300 | |
| 301 | // ROLLUP(country) with plain region produces: |
| 302 | // Set 1: (region, country) — 4 combos: AMER/US, AMER/CA, EMEA/DE, EMEA/FR |
| 303 | // Set 2: (region) — 2 rows: AMER, EMEA (country=NULL) |
| 304 | // Total = 6 |
| 305 | assert_eq!( |
| 306 | rows.len(), |
| 307 | 6, |
| 308 | "expected 6 rows for mixed plain+rollup, got {}: {:?}", |
| 309 | rows.len(), |
| 310 | rows |
| 311 | ); |
| 312 | |
| 313 | // region is NEVER NULL (it's a plain key, always present). |
| 314 | for row in &rows { |
| 315 | let region = row.first().map(|s| s.as_str()).unwrap_or(""); |
| 316 | assert!( |
| 317 | !region.is_empty(), |
| 318 | "region must never be NULL in mixed plain+rollup, but got: {row:?}" |
| 319 | ); |
| 320 | } |
| 321 | |
| 322 | // ROLLUP suffix: rows with country=NULL represent regional subtotals. |
| 323 | let regional = rows |
| 324 | .iter() |
| 325 | .filter(|r| r.get(1).map(|s| s.is_empty()).unwrap_or(false)) |
| 326 | .count(); |
| 327 | assert_eq!( |
| 328 | regional, 2, |
| 329 | "expected 2 regional subtotal rows (AMER, EMEA)" |
| 330 | ); |
| 331 | } |
| 332 | |
| 333 | /// Empty grouping set `()` must produce exactly one grand-total row. |
| 334 | #[tokio::test(flavor = "multi_thread", worker_threads = 4)] |
nothing calls this directly
no test coverage detected