Parse complete query with clean precedence: core query + modifiers This implements Option 3: Restructured Parser Precedence
(tokens: &[Token])
| 407 | /// Parse complete query with clean precedence: core query + modifiers |
| 408 | /// This implements Option 3: Restructured Parser Precedence |
| 409 | fn parse_set_operation(tokens: &[Token]) -> IResult<&[Token], Query> { |
| 410 | // Step 1: Parse the core query (UNION, INTERSECT, MATCH, etc.) |
| 411 | let (remaining, core_query) = parse_core_query(tokens)?; |
| 412 | |
| 413 | log::debug!( |
| 414 | "parse_set_operation: core_query type = {:?}", |
| 415 | std::mem::discriminant(&core_query) |
| 416 | ); |
| 417 | match &core_query { |
| 418 | Query::Basic(bq) => { |
| 419 | log::debug!("parse_set_operation: BasicQuery has group_clause={}, order_clause={}, limit_clause={}", |
| 420 | bq.group_clause.is_some(), bq.order_clause.is_some(), bq.limit_clause.is_some()); |
| 421 | } |
| 422 | Query::Limited { |
| 423 | query, |
| 424 | order_clause, |
| 425 | limit_clause, |
| 426 | } => { |
| 427 | log::debug!( |
| 428 | "parse_set_operation: Limited query has order={}, limit={}", |
| 429 | order_clause.is_some(), |
| 430 | limit_clause.is_some() |
| 431 | ); |
| 432 | if let Query::Basic(bq) = query.as_ref() { |
| 433 | log::debug!("parse_set_operation: Wrapped BasicQuery has group_clause={}, order_clause={}, limit_clause={}", |
| 434 | bq.group_clause.is_some(), bq.order_clause.is_some(), bq.limit_clause.is_some()); |
| 435 | } |
| 436 | } |
| 437 | _ => { |
| 438 | log::debug!("parse_set_operation: Other query type"); |
| 439 | } |
| 440 | } |
| 441 | |
| 442 | // Step 2: Parse optional modifiers that can apply to any query |
| 443 | let (remaining, order_clause) = opt(order_clause)(remaining)?; |
| 444 | let (remaining, limit_clause) = opt(limit_clause)(remaining)?; |
| 445 | |
| 446 | log::debug!( |
| 447 | "parse_set_operation: Parsed order_clause={}, limit_clause={}", |
| 448 | order_clause.is_some(), |
| 449 | limit_clause.is_some() |
| 450 | ); |
| 451 | |
| 452 | // Step 3: Apply modifiers using unified logic |
| 453 | let final_query = apply_query_modifiers(core_query, order_clause, limit_clause); |
| 454 | |
| 455 | log::debug!( |
| 456 | "parse_set_operation: final_query type = {:?}", |
| 457 | std::mem::discriminant(&final_query) |
| 458 | ); |
| 459 | |
| 460 | Ok((remaining, final_query)) |
| 461 | } |
| 462 | |
| 463 | /// Parse UNION and EXCEPT operations (lower precedence) |
| 464 | fn parse_union_except(tokens: &[Token]) -> IResult<&[Token], Query> { |
no test coverage detected