| 244 | } |
| 245 | |
| 246 | fn resolve_projected_fields(&self, projected_fields: &[String]) -> Result<Vec<DataField>> { |
| 247 | if projected_fields.is_empty() { |
| 248 | return Ok(Vec::new()); |
| 249 | } |
| 250 | |
| 251 | let full_name = self.table.identifier().full_name(); |
| 252 | let field_map: HashMap<&str, &DataField> = self |
| 253 | .table |
| 254 | .schema |
| 255 | .fields() |
| 256 | .iter() |
| 257 | .map(|field| (field.name(), field)) |
| 258 | .collect(); |
| 259 | |
| 260 | let mut seen = HashSet::with_capacity(projected_fields.len()); |
| 261 | let mut resolved = Vec::with_capacity(projected_fields.len()); |
| 262 | |
| 263 | for name in projected_fields { |
| 264 | if !seen.insert(name.as_str()) { |
| 265 | return Err(Error::ConfigInvalid { |
| 266 | message: format!("Duplicate projection column '{name}' for table {full_name}"), |
| 267 | }); |
| 268 | } |
| 269 | |
| 270 | if name == crate::spec::ROW_ID_FIELD_NAME { |
| 271 | resolved.push(DataField::new( |
| 272 | crate::spec::ROW_ID_FIELD_ID, |
| 273 | crate::spec::ROW_ID_FIELD_NAME.to_string(), |
| 274 | crate::spec::DataType::BigInt(crate::spec::BigIntType::with_nullable(true)), |
| 275 | )); |
| 276 | continue; |
| 277 | } |
| 278 | |
| 279 | let field = field_map |
| 280 | .get(name.as_str()) |
| 281 | .ok_or_else(|| Error::ColumnNotExist { |
| 282 | full_name: full_name.clone(), |
| 283 | column: name.clone(), |
| 284 | })?; |
| 285 | resolved.push((*field).clone()); |
| 286 | } |
| 287 | |
| 288 | Ok(resolved) |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | #[cfg(test)] |