diff --git a/core/translate/display.rs b/core/translate/display.rs index 41a6e92ef..25a5744f8 100644 --- a/core/translate/display.rs +++ b/core/translate/display.rs @@ -235,7 +235,7 @@ pub struct PlanContext<'a>(pub &'a [&'a TableReferences]); // Definitely not perfect yet impl ToSqlContext for PlanContext<'_> { - fn get_column_name(&self, table_id: TableInternalId, col_idx: usize) -> Option<&str> { + fn get_column_name(&self, table_id: TableInternalId, col_idx: usize) -> Option> { let Some(table) = self .0 .iter() @@ -246,10 +246,7 @@ impl ToSqlContext for PlanContext<'_> { let cols = table.columns(); match cols.get(col_idx) { None => None, - Some(col) => match col.name.as_ref() { - None => None, - Some(n) => Some(n), - }, + Some(col) => Some(col.name.as_ref().map(|name| name.as_ref())), } } diff --git a/core/translate/main_loop.rs b/core/translate/main_loop.rs index 2617c86d8..51260715b 100644 --- a/core/translate/main_loop.rs +++ b/core/translate/main_loop.rs @@ -1,4 +1,4 @@ -use turso_parser::ast::SortOrder; +use turso_parser::ast::{fmt::ToTokens, SortOrder}; use std::sync::Arc; @@ -20,6 +20,7 @@ use crate::{ use super::{ aggregation::translate_aggregation_step, + display::PlanContext, emitter::{OperationMode, TranslateCtx}, expr::{ translate_condition_expr, translate_expr, translate_expr_no_constant_opt, @@ -77,12 +78,18 @@ pub fn init_distinct(program: &mut ProgramBuilder, plan: &SelectPlan) -> Distinc .result_columns .iter() .enumerate() - .map(|(i, col)| IndexColumn { - name: col.expr.to_string(), - order: SortOrder::Asc, - pos_in_table: i, - collation: None, // FIXME: this should be determined based on the result column expression! - default: None, // FIXME: this should be determined based on the result column expression! + .map(|(i, col)| { + IndexColumn { + name: col + .expr + .displayer(&PlanContext(&[&plan.table_references])) + .to_string() + .unwrap(), + order: SortOrder::Asc, + pos_in_table: i, + collation: None, // FIXME: this should be determined based on the result column expression! + default: None, // FIXME: this should be determined based on the result column expression! + } }) .collect(), unique: false, diff --git a/parser/src/ast/fmt.rs b/parser/src/ast/fmt.rs index 3f9d842ad..b15cbb12a 100644 --- a/parser/src/ast/fmt.rs +++ b/parser/src/ast/fmt.rs @@ -12,6 +12,7 @@ use crate::ast::TableInternalId; /// Context to be used in ToSqlString pub trait ToSqlContext { /// Given an id, get the table name + /// First Option indicates whether the table exists /// /// Currently not considering aliases fn get_table_name(&self, _id: TableInternalId) -> Option<&str> { @@ -19,9 +20,22 @@ pub trait ToSqlContext { } /// Given a table id and a column index, get the column name - fn get_column_name(&self, _table_id: TableInternalId, _col_idx: usize) -> Option<&str> { + /// First Option indicates whether the column exists + /// Second Option indicates whether the column has a name + fn get_column_name(&self, _table_id: TableInternalId, _col_idx: usize) -> Option> { None } + + /// Helper to get a flat column name + /// If the column exists and has a name, return the name + /// If the column exists but has no name, return the index as string + fn get_flat_column_name(&self, table_id: TableInternalId, col_idx: usize) -> Option { + match self.get_column_name(table_id, col_idx) { + Some(Some(name)) => Some(name.to_string()), + Some(None) => Some(format!("{col_idx}")), + None => None, + } + } } pub struct WriteTokenStream<'a, T: Write> { @@ -780,7 +794,13 @@ impl ToTokens for Expr { Self::Column { table, column, .. } => { s.append(TK_ID, context.get_table_name(*table))?; s.append(TK_DOT, None)?; - s.append(TK_ID, context.get_column_name(*table, *column)) + s.append( + TK_ID, + context + .get_flat_column_name(*table, *column) + .as_ref() + .map(|s| s.as_ref()), + ) } Self::InList { lhs, not, rhs } => { lhs.to_tokens(s, context)?;