Skip to content

Commit

Permalink
sql: simplify Label
Browse files Browse the repository at this point in the history
  • Loading branch information
erikgrinaker committed Jul 17, 2024
1 parent 6478996 commit 97f54aa
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 43 deletions.
4 changes: 2 additions & 2 deletions src/bin/toysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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("|"));
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/sql/planner/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions src/sql/planner/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand All @@ -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.
Expand Down
49 changes: 17 additions & 32 deletions src/sql/types/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,14 +373,14 @@ dyn_clone::clone_trait_object!(RowIterator);

impl<I: Iterator<Item = Result<Row>> + 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),
}

Expand All @@ -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<String>) -> 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<String>, 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<ast::Expression> {
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<Label> for ast::Expression {
/// Builds an ast::Expression::Field for a label. Can't be None.
fn from(label: Label) -> Self {
match label {
Label::Qualified(table, column) => ast::Expression::Field(Some(table), column),
Label::Unqualified(column) => ast::Expression::Field(None, column),
Label::None => panic!("can't convert None label to AST expression"), // shouldn't happen
}
}
}

/// Returns true if the label is None.
pub fn is_none(&self) -> bool {
matches!(self, Self::None)
}

/// Returns true if the label is not None.
pub fn is_some(&self) -> bool {
!self.is_none()
impl From<Option<String>> for Label {
fn from(name: Option<String>) -> Self {
name.map(Label::Unqualified).unwrap_or(Label::None)
}
}

0 comments on commit 97f54aa

Please sign in to comment.