Parse multi-row VALUES clause like (val1, val2), (val3, val4)
(values_str: &str)
| 441 | |
| 442 | /// Parse multi-row VALUES clause like (val1, val2), (val3, val4) |
| 443 | fn parse_multi_row_values(values_str: &str) -> Vec<Vec<String>> { |
| 444 | let mut result = Vec::new(); |
| 445 | let mut current_set = Vec::new(); |
| 446 | let mut current_value = String::new(); |
| 447 | let mut in_quotes = false; |
| 448 | let mut quote_char = ' '; |
| 449 | let mut paren_depth = 0; |
| 450 | let mut in_value_set = false; |
| 451 | let mut in_comment = false; |
| 452 | |
| 453 | let chars: Vec<char> = values_str.chars().collect(); |
| 454 | let mut i = 0; |
| 455 | |
| 456 | while i < chars.len() { |
| 457 | let ch = chars[i]; |
| 458 | |
| 459 | // Handle SQL comments |
| 460 | if !in_quotes && !in_comment && ch == '-' && i + 1 < chars.len() && chars[i + 1] == '-' { |
| 461 | // Start of comment, skip to end of line |
| 462 | in_comment = true; |
| 463 | i += 2; |
| 464 | continue; |
| 465 | } |
| 466 | |
| 467 | if in_comment { |
| 468 | if ch == '\n' { |
| 469 | in_comment = false; |
| 470 | } |
| 471 | i += 1; |
| 472 | continue; |
| 473 | } |
| 474 | |
| 475 | match ch { |
| 476 | '(' if !in_quotes => { |
| 477 | paren_depth += 1; |
| 478 | if paren_depth == 1 { |
| 479 | in_value_set = true; |
| 480 | } else { |
| 481 | current_value.push(ch); |
| 482 | } |
| 483 | } |
| 484 | ')' if !in_quotes => { |
| 485 | paren_depth -= 1; |
| 486 | if paren_depth == 0 && in_value_set { |
| 487 | // End of value set |
| 488 | if !current_value.is_empty() { |
| 489 | current_set.push(current_value.trim().trim_matches('\'').trim_matches('"').to_string()); |
| 490 | current_value.clear(); |
| 491 | } |
| 492 | if !current_set.is_empty() { |
| 493 | result.push(current_set.clone()); |
| 494 | current_set.clear(); |
| 495 | } |
| 496 | in_value_set = false; |
| 497 | } else { |
| 498 | current_value.push(ch); |
| 499 | } |
| 500 | } |
no test coverage detected