MCPcopy Create free account
hub / github.com/erans/pgsqlite / extract_column_mappings_from_query

Function extract_column_mappings_from_query

src/query/executor.rs:2604–2678  ·  view source on GitHub ↗

Extract column mappings from SELECT query with AS aliases

(query: &str, table: &str)

Source from the content-addressed store, hash-verified

2602
2603/// Extract column mappings from SELECT query with AS aliases
2604fn extract_column_mappings_from_query(query: &str, table: &str) -> std::collections::HashMap<String, String> {
2605 use regex::Regex;
2606 use std::collections::HashMap;
2607
2608 let mut mappings = HashMap::new();
2609
2610 debug!("extract_column_mappings_from_query: query='{}', table='{}'", query, table);
2611
2612 // First, try to match patterns like "table.column_name AS alias"
2613 let table_pattern = Regex::new(&format!(
2614 r"(?i)\b{}\.(\w+)\s+AS\s+(\w+)",
2615 regex::escape(table)
2616 ));
2617
2618 if let Ok(re) = table_pattern {
2619 debug!("Table pattern regex created: {:?}", re.as_str());
2620 let matches_found = re.captures_iter(query).count();
2621 debug!("Table pattern matches found: {}", matches_found);
2622
2623 for captures in re.captures_iter(query) {
2624 if let (Some(source_col), Some(alias)) = (captures.get(1), captures.get(2)) {
2625 let source_column = source_col.as_str().to_string();
2626 let alias_name = alias.as_str().to_string();
2627
2628 debug!("Column mapping (with table prefix): {} -> {}.{}", alias_name, table, source_column);
2629 mappings.insert(alias_name, source_column);
2630 }
2631 }
2632 } else {
2633 debug!("Failed to create table pattern regex");
2634 }
2635
2636 // Also match simple patterns like "column_name AS alias" (without table prefix)
2637 // This is common in queries like "SELECT id AS event_id, created_at AS event_created_at FROM events"
2638 // BUT we need to be careful not to match the table name in "table.column AS alias" patterns
2639 let simple_pattern = Regex::new(r"(?i)(?:^|,|\s)(\w+)\s+AS\s+(\w+)");
2640
2641 if let Ok(re) = simple_pattern {
2642 for captures in re.captures_iter(query) {
2643 if let (Some(source_col), Some(alias)) = (captures.get(1), captures.get(2)) {
2644 let source_column = source_col.as_str().to_string();
2645 let alias_name = alias.as_str().to_string();
2646
2647 // Only add if we haven't already found this alias with a table prefix
2648 // (table-prefixed mappings are more specific and should take precedence)
2649 if let std::collections::hash_map::Entry::Vacant(e) = mappings.entry(alias_name.clone()) {
2650 // Check if this is actually a table name (if the character before it is a dot)
2651 // We need to look at the full match to see if there's a dot before
2652 let _full_match = captures.get(0).unwrap().as_str();
2653 // Skip if this looks like it's part of a table.column pattern
2654 // (i.e., the source_column is actually the table name)
2655 if !query.contains(&format!("{source_column}.{alias_name}")) &&
2656 !query.contains(&format!("{source_column}.")) {
2657 debug!("Column mapping (simple alias): {} -> {}", alias_name, source_column);
2658 e.insert(source_column);
2659 }
2660 }
2661 }

Callers 2

execute_selectMethod · 0.85

Calls 3

getMethod · 0.45
insertMethod · 0.45
cloneMethod · 0.45

Tested by

no test coverage detected