Try to extract the source table and column for an alias in a simple SELECT e.g., "SELECT test_users.id AS users_id" -> returns ("test_users", "id") e.g., "SELECT id AS event_id FROM test_events" -> returns ("test_events", "id")
(query: &str, alias: &str)
| 1033 | /// e.g., "SELECT test_users.id AS users_id" -> returns ("test_users", "id") |
| 1034 | /// e.g., "SELECT id AS event_id FROM test_events" -> returns ("test_events", "id") |
| 1035 | fn extract_source_table_column_for_alias(query: &str, alias: &str) -> Option<(String, String)> { |
| 1036 | // This is a simple heuristic for the common case |
| 1037 | // Look for "SELECT <expr> as <alias>" pattern |
| 1038 | info!("extract_source_table_column_for_alias: Looking for alias '{}' in query", alias); |
| 1039 | let query_upper = query.to_uppercase(); |
| 1040 | let alias_upper = alias.to_uppercase(); |
| 1041 | |
| 1042 | // Find "AS <alias>" in the query |
| 1043 | let as_pattern = format!(" AS {alias_upper}"); |
| 1044 | info!("Looking for pattern: '{}'", as_pattern); |
| 1045 | if let Some(as_pos) = query_upper.find(&as_pattern) { |
| 1046 | info!("Found AS pattern at position {}", as_pos); |
| 1047 | // Work backwards to find the start of the expression |
| 1048 | let before_as = &query[..as_pos]; |
| 1049 | |
| 1050 | // Find the column expression before AS |
| 1051 | // Handle both "table.column" and "column" patterns |
| 1052 | |
| 1053 | // Get the last token/word before AS (handling commas and spaces) |
| 1054 | let trimmed = before_as.trim_end(); |
| 1055 | info!("Text before AS (trimmed): '{}'", trimmed); |
| 1056 | |
| 1057 | // Find where this expression starts (after SELECT or comma) |
| 1058 | let mut expr_start = 0; |
| 1059 | let select_upper = "SELECT "; |
| 1060 | |
| 1061 | // Look for the last comma or SELECT keyword |
| 1062 | if let Some(comma_pos) = trimmed.rfind(',') { |
| 1063 | expr_start = comma_pos + 1; |
| 1064 | info!("Found comma at position {}, expr_start = {}", comma_pos, expr_start); |
| 1065 | } else if let Some(select_pos) = query_upper.find(select_upper) { |
| 1066 | expr_start = select_pos + select_upper.len(); |
| 1067 | info!("Found SELECT at position {}, expr_start = {}", select_pos, expr_start); |
| 1068 | } |
| 1069 | |
| 1070 | // Make sure expr_start is within bounds |
| 1071 | if expr_start >= trimmed.len() { |
| 1072 | info!("expr_start {} >= trimmed.len() {}, using 0", expr_start, trimmed.len()); |
| 1073 | expr_start = 0; |
| 1074 | } |
| 1075 | |
| 1076 | let expr = trimmed[expr_start..].trim(); |
| 1077 | info!("Extracted expression: '{}'", expr); |
| 1078 | |
| 1079 | // Check if it contains a dot (table.column) |
| 1080 | if let Some(dot_pos) = expr.rfind('.') { |
| 1081 | let table_part = expr[..dot_pos].trim(); |
| 1082 | let column_part = expr[dot_pos + 1..].trim(); |
| 1083 | info!("Found table.column pattern: '{}' . '{}'", table_part, column_part); |
| 1084 | |
| 1085 | // Validate both parts are simple identifiers |
| 1086 | if table_part.chars().all(|c| c.is_alphanumeric() || c == '_') && |
| 1087 | column_part.chars().all(|c| c.is_alphanumeric() || c == '_') { |
| 1088 | info!("Successfully parsed alias '{}' -> table '{}', column '{}'", alias, table_part, column_part); |
| 1089 | return Some((table_part.to_string(), column_part.to_string())); |
| 1090 | } |
| 1091 | } |
| 1092 | // For simple column references without table prefix |
nothing calls this directly
no test coverage detected