Attempts to extract column names from an S-String to avoid wildcards when possible
(
columns: Vec<RelationColumn>,
items: &[InterpolateItem<rq::Expr>],
)
| 1043 | |
| 1044 | /// Attempts to extract column names from an S-String to avoid wildcards when possible |
| 1045 | fn try_extract_sql_columns( |
| 1046 | columns: Vec<RelationColumn>, |
| 1047 | items: &[InterpolateItem<rq::Expr>], |
| 1048 | ) -> Vec<RelationColumn> { |
| 1049 | use sqlparser::ast; |
| 1050 | |
| 1051 | let mut has_wildcard = false; |
| 1052 | |
| 1053 | let sql_columns = items |
| 1054 | .iter() |
| 1055 | .map(|item| match item { |
| 1056 | InterpolateItem::String(s) => { |
| 1057 | let sql_ast = |
| 1058 | sqlparser::parser::Parser::parse_sql(&sqlparser::dialect::GenericDialect {}, s) |
| 1059 | .map_err(|err| format!("could not parse {item:?}: {err:?}"))?; |
| 1060 | if sql_ast.len() != 1 { |
| 1061 | return Err(format!( |
| 1062 | "expected exactly one statement, got {}", |
| 1063 | sql_ast.len() |
| 1064 | )); |
| 1065 | } |
| 1066 | |
| 1067 | let statement = sql_ast.into_iter().next().unwrap(); |
| 1068 | |
| 1069 | if let sqlparser::ast::Statement::Query(query) = statement { |
| 1070 | if let sqlparser::ast::SetExpr::Select(select_stmt) = *query.body { |
| 1071 | select_stmt |
| 1072 | .projection |
| 1073 | .into_iter() |
| 1074 | .map(|expr| match expr { |
| 1075 | ast::SelectItem::UnnamedExpr(expr) => { |
| 1076 | if let ast::Expr::Identifier(ast::Ident { value, .. }) = expr { |
| 1077 | Ok(value) |
| 1078 | } else { |
| 1079 | Err(format!("Only Idents are supported, got {expr:?}")) |
| 1080 | } |
| 1081 | } |
| 1082 | ast::SelectItem::ExprWithAlias { alias, .. } => Ok(alias.value), // Store alias |
| 1083 | ast::SelectItem::ExprWithAliases { .. } => Err( |
| 1084 | "Multi-alias projection (`expr AS (a, b)`) is not supported" |
| 1085 | .into(), |
| 1086 | ), |
| 1087 | ast::SelectItem::QualifiedWildcard(_, _) |
| 1088 | | ast::SelectItem::Wildcard(_) => { |
| 1089 | has_wildcard = true; |
| 1090 | Err("columns contain a wildcard".into()) |
| 1091 | } |
| 1092 | }) |
| 1093 | .collect::<Result<Vec<String>, String>>() |
| 1094 | } else { |
| 1095 | Err(format!("not a SELECT statement: {query:?}")) |
| 1096 | } |
| 1097 | } else { |
| 1098 | Err(format!("not a Query: {statement:?}")) |
| 1099 | } |
| 1100 | } |
| 1101 | InterpolateItem::Expr { .. } => Err(format!( |
| 1102 | "could not extract columns from item {item:?}: not a string" |