1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use {
	super::SelectItem,
	crate::{
		executor::{types::ColumnInfo, PlannedRecipe},
		Error, PlanError, Result,
	},
};

pub(crate) fn refine_item(
	index: usize,
	select_item: SelectItem,
	columns: &[ColumnInfo],
	include_table: bool,
) -> Result<Vec<(PlannedRecipe, String)>> {
	Ok(match select_item {
		SelectItem::Recipe(meta_recipe, alias) => {
			let recipe = PlannedRecipe::new(meta_recipe, columns)?;
			let label = alias.unwrap_or_else(|| recipe.get_label(index, include_table, &columns));
			vec![(recipe, label)]
		}
		SelectItem::Wildcard(specifier) => {
			let specified_table = specifier.and_then(|specifier| specifier.get(0).cloned());
			let matches_table = |column: &ColumnInfo| {
				specified_table
					.clone()
					.map(|specified_table| {
						column.table.name == specified_table
							|| column
								.table
								.alias
								.clone()
								.map(|alias| alias == specified_table)
								.unwrap_or(false)
					})
					.unwrap_or(true)
			};
			columns
				.iter()
				.enumerate()
				.filter_map(|(index, column)| {
					if matches_table(column) {
						Some((
							PlannedRecipe::of_index(index),
							if include_table {
								format!("{}.{}", column.table.name, column.name)
							} else {
								column.name.clone()
							},
						))
					} else {
						None
					}
				})
				.collect()
		}
	})
}

pub(crate) fn refine_items(
	select_items: Vec<SelectItem>,
	columns: &[ColumnInfo],
	include_table: bool,
) -> Result<Vec<(PlannedRecipe, String)>> {
	select_items
		.into_iter()
		.enumerate()
		.map(|(index, select_item)| refine_item(index, select_item, &columns, include_table))
		.collect::<Result<Vec<Vec<(PlannedRecipe, String)>>>>()?
		.into_iter()
		.reduce(|mut select_items, select_item_set| {
			select_items.extend(select_item_set);
			select_items
		})
		.ok_or(Error::Plan(PlanError::UnreachableNoSelectItems))
}