diff --git a/src/bin/toysql.rs b/src/bin/toysql.rs index d7c485d7f..495a410a4 100644 --- a/src/bin/toysql.rs +++ b/src/bin/toysql.rs @@ -199,10 +199,10 @@ Storage: {keys} keys, {logical_size} MB logical, {nodes}x {disk_size} MB disk, StatementResult::Explain(plan) => println!("{}", plan), StatementResult::Select { columns, rows } => { if self.show_headers { - println!("{}", columns.into_iter().map(|c| c.as_header()).join("|")); + println!("{}", columns.iter().map(|c| c.as_header()).join("|")); } for row in rows { - println!("{}", row.into_iter().map(|v| v.to_string()).join("|")); + println!("{}", row.iter().join("|")); } } } diff --git a/src/sql/planner/plan.rs b/src/sql/planner/plan.rs index 15debc4b3..d0f4f79f5 100644 --- a/src/sql/planner/plan.rs +++ b/src/sql/planner/plan.rs @@ -268,13 +268,13 @@ impl Node { /// Returns a label for a column, if any. Only used for display purposes. pub fn column_label(&self, index: usize) -> Label { match self { - // Source nodes use the table/column name, calling name() to handle - // any aliases. - Self::IndexLookup { table, .. } - | Self::KeyLookup { table, .. } - | Self::Scan { table, .. } => { - Label::maybe_qualified(self.name(), table.columns[index].name.clone()) - } + // Source nodes use the table/column name. + Self::IndexLookup { table, alias, .. } + | Self::KeyLookup { table, alias, .. } + | Self::Scan { table, alias, .. } => Label::Qualified( + alias.as_ref().unwrap_or(&table.name).clone(), + table.columns[index].name.clone(), + ), // Some nodes rearrange columns. Route them to the correct // upstream column where appropriate. diff --git a/src/sql/planner/planner.rs b/src/sql/planner/planner.rs index b78f272a6..9356b96c7 100644 --- a/src/sql/planner/planner.rs +++ b/src/sql/planner/planner.rs @@ -184,7 +184,7 @@ impl<'a, C: Catalog> Planner<'a, C> { // verify that they're all used in GROUP BY as well. if select.is_empty() { select = (0..node.size()) - .map(|i| (node.column_label(i).into_ast_field().expect("no FROM label"), None)) + .map(|i| (ast::Expression::from(node.column_label(i)), None)) .collect(); } node = self.build_aggregate(&mut scope, node, group_by, aggregates)?; @@ -200,7 +200,7 @@ impl<'a, C: Catalog> Planner<'a, C> { let mut labels = Vec::with_capacity(select.len()); for (expr, alias) in select { expressions.push(Self::build_expression(expr, &scope)?); - labels.push(Label::maybe_name(alias)); + labels.push(Label::from(alias)); } // Add hidden columns for HAVING and ORDER BY columns not in SELECT. diff --git a/src/sql/types/value.rs b/src/sql/types/value.rs index d8967066e..22b13cfc4 100644 --- a/src/sql/types/value.rs +++ b/src/sql/types/value.rs @@ -373,14 +373,14 @@ dyn_clone::clone_trait_object!(RowIterator); impl> + DynClone> RowIterator for I {} -/// A column label, used in result sets and query plans. +/// A column label, used in query results and plans. #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum Label { /// No label. None, /// An unqualified column name. Unqualified(String), - /// A fully qualified column name. + /// A fully qualified table/column name. Qualified(String, String), } @@ -395,43 +395,28 @@ impl std::fmt::Display for Label { } impl Label { - /// Creates an unqualified label for a Some. - pub fn maybe_name(name: Option) -> Self { - name.map(Self::Unqualified).unwrap_or(Self::None) - } - - /// Creates a qualified label if table is given, otherwise unqualified. - pub fn maybe_qualified(table: Option, column: String) -> Self { - match table { - Some(table) => Self::Qualified(table, column), - None => Self::Unqualified(column), - } - } - /// Formats the label as a short column header. - pub fn as_header(&self) -> String { + pub fn as_header(&self) -> &str { match self { - Self::Qualified(_, column) | Self::Unqualified(column) => column.to_string(), - Self::None => "?".to_string(), + Self::Qualified(_, column) | Self::Unqualified(column) => column.as_str(), + Self::None => "?", } } +} - /// Converts the label into an AST field expression. - pub fn into_ast_field(self) -> Option { - match self { - Label::Qualified(table, column) => Some(ast::Expression::Field(Some(table), column)), - Label::Unqualified(column) => Some(ast::Expression::Field(None, column)), - Label::None => None, +impl From