From 399f10fe9a5906a4633ffdb16c2e255416d60154 Mon Sep 17 00:00:00 2001 From: TcMits Date: Sat, 23 Aug 2025 19:16:26 +0700 Subject: [PATCH 1/8] refactor parser fmt --- core/translate/display.rs | 69 +-- core/translate/optimizer/mod.rs | 3 +- parser/src/ast.rs | 7 - parser/src/ast/fmt.rs | 831 ++++++++++++++++---------------- parser/src/error.rs | 3 + parser/src/parser.rs | 29 +- 6 files changed, 475 insertions(+), 467 deletions(-) diff --git a/core/translate/display.rs b/core/translate/display.rs index 631e5a295..41a6e92ef 100644 --- a/core/translate/display.rs +++ b/core/translate/display.rs @@ -235,44 +235,51 @@ 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) -> String { - let table = self + fn get_column_name(&self, table_id: TableInternalId, col_idx: usize) -> Option<&str> { + let Some(table) = self .0 .iter() .find_map(|table_ref| table_ref.find_table_by_internal_id(table_id)) - .unwrap(); + else { + return None; + }; let cols = table.columns(); - match cols.get(col_idx).unwrap().name.as_ref() { - None => format!("{col_idx}"), - Some(n) => n.to_string(), + match cols.get(col_idx) { + None => None, + Some(col) => match col.name.as_ref() { + None => None, + Some(n) => Some(n), + }, } } - fn get_table_name(&self, id: TableInternalId) -> &str { - let table_ref = self + fn get_table_name(&self, id: TableInternalId) -> Option<&str> { + let Some(table_ref) = self .0 .iter() .find(|table_ref| table_ref.find_table_by_internal_id(id).is_some()) - .unwrap(); + else { + return None; + }; let joined_table = table_ref.find_joined_table_by_internal_id(id); let outer_query = table_ref.find_outer_query_ref_by_internal_id(id); match (joined_table, outer_query) { - (Some(table), None) => &table.identifier, - (None, Some(table)) => &table.identifier, + (Some(table), None) => Some(&table.identifier), + (None, Some(table)) => Some(&table.identifier), _ => unreachable!(), } } } impl ToTokens for Plan { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { match self { Self::Select(select) => { - select.to_tokens_with_context(s, &PlanContext(&[&select.table_references]))?; + select.to_tokens(s, &PlanContext(&[&select.table_references]))?; } Self::CompoundSelect { left, @@ -289,11 +296,11 @@ impl ToTokens for Plan { let context = &PlanContext(all_refs.as_slice()); for (plan, operator) in left { - plan.to_tokens_with_context(s, context)?; - operator.to_tokens_with_context(s, context)?; + plan.to_tokens(s, context)?; + operator.to_tokens(s, context)?; } - right_most.to_tokens_with_context(s, context)?; + right_most.to_tokens(s, context)?; if let Some(order_by) = order_by { s.append(TokenType::TK_ORDER, None)?; @@ -319,8 +326,8 @@ impl ToTokens for Plan { s.append(TokenType::TK_FLOAT, Some(&offset.to_string()))?; } } - Self::Delete(delete) => delete.to_tokens_with_context(s, context)?, - Self::Update(update) => update.to_tokens_with_context(s, context)?, + Self::Delete(delete) => delete.to_tokens(s, context)?, + Self::Update(update) => update.to_tokens(s, context)?, } Ok(()) @@ -328,7 +335,7 @@ impl ToTokens for Plan { } impl ToTokens for JoinedTable { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _context: &C, @@ -345,7 +352,7 @@ impl ToTokens for JoinedTable { Table::FromClauseSubquery(from_clause_subquery) => { s.append(TokenType::TK_LP, None)?; // Could possibly merge the contexts together here - from_clause_subquery.plan.to_tokens_with_context( + from_clause_subquery.plan.to_tokens( s, &PlanContext(&[&from_clause_subquery.plan.table_references]), )?; @@ -362,7 +369,7 @@ impl ToTokens for JoinedTable { // TODO: currently cannot print the original CTE as it is optimized into a subquery impl ToTokens for SelectPlan { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -374,7 +381,7 @@ impl ToTokens for SelectPlan { .map(|values| values.iter().map(|v| Box::from(v.clone())).collect()) .collect(), ) - .to_tokens_with_context(s, context)?; + .to_tokens(s, context)?; } else { s.append(TokenType::TK_SELECT, None)?; if self.distinctness.is_distinct() { @@ -386,7 +393,7 @@ impl ToTokens for SelectPlan { s.append(TokenType::TK_COMMA, None)?; } - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; if let Some(alias) = alias { s.append(TokenType::TK_AS, None)?; s.append(TokenType::TK_ID, Some(alias))?; @@ -403,7 +410,7 @@ impl ToTokens for SelectPlan { } let table_ref = self.joined_tables().get(order.original_idx).unwrap(); - table_ref.to_tokens_with_context(s, context)?; + table_ref.to_tokens(s, context)?; } if !self.where_clause.is_empty() { @@ -418,7 +425,7 @@ impl ToTokens for SelectPlan { if i != 0 { s.append(TokenType::TK_AND, None)?; } - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; } } @@ -436,7 +443,7 @@ impl ToTokens for SelectPlan { if i != 0 { s.append(TokenType::TK_AND, None)?; } - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; } } } @@ -471,7 +478,7 @@ impl ToTokens for SelectPlan { } impl ToTokens for DeletePlan { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -500,7 +507,7 @@ impl ToTokens for DeletePlan { if i != 0 { s.append(TokenType::TK_AND, None)?; } - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; } } @@ -533,7 +540,7 @@ impl ToTokens for DeletePlan { } impl ToTokens for UpdatePlan { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -578,10 +585,10 @@ impl ToTokens for UpdatePlan { .map(|where_clause| where_clause.expr.clone()); iter.next() .expect("should not be empty") - .to_tokens_with_context(s, context)?; + .to_tokens(s, context)?; for expr in iter { s.append(TokenType::TK_AND, None)?; - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; } } diff --git a/core/translate/optimizer/mod.rs b/core/translate/optimizer/mod.rs index e34b46e91..03da50566 100644 --- a/core/translate/optimizer/mod.rs +++ b/core/translate/optimizer/mod.rs @@ -54,7 +54,8 @@ pub fn optimize_plan(plan: &mut Plan, schema: &Schema) -> Result<()> { // When debug tracing is enabled, print the optimized plan as a SQL string for debugging tracing::debug!( plan_sql = plan - .format_with_context(&crate::translate::display::PlanContext(&[])) + .displayer(&crate::translate::display::PlanContext(&[])) + .to_string() .unwrap() ); Ok(()) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 440685014..ce931027c 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -856,13 +856,6 @@ pub struct QualifiedName { pub alias: Option, // FIXME restrict alias usage (fullname vs xfullname) } -impl std::fmt::Display for QualifiedName { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use fmt::ToTokens as _; - self.to_fmt(f) - } -} - /// `ALTER TABLE` body // https://sqlite.org/lang_altertable.html #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/parser/src/ast/fmt.rs b/parser/src/ast/fmt.rs index 16cf635d2..3f9d842ad 100644 --- a/parser/src/ast/fmt.rs +++ b/parser/src/ast/fmt.rs @@ -2,8 +2,10 @@ use std::fmt::{self, Display, Formatter, Write}; use crate::ast::*; +use crate::error::Error; use crate::token::TokenType; use crate::token::TokenType::*; +use crate::Result; use crate::ast::TableInternalId; @@ -12,62 +14,35 @@ pub trait ToSqlContext { /// Given an id, get the table name /// /// Currently not considering aliases - fn get_table_name(&self, id: TableInternalId) -> &str; + fn get_table_name(&self, _id: TableInternalId) -> Option<&str> { + None + } + /// Given a table id and a column index, get the column name - fn get_column_name(&self, table_id: TableInternalId, col_idx: usize) -> String; -} - -struct FmtTokenStream<'a, 'b> { - f: &'a mut Formatter<'b>, - spaced: bool, -} - -impl TokenStream for FmtTokenStream<'_, '_> { - type Error = fmt::Error; - - fn append(&mut self, ty: TokenType, value: Option<&str>) -> fmt::Result { - if !self.spaced { - match ty { - TK_COMMA | TK_SEMI | TK_RP | TK_DOT => {} - _ => { - self.f.write_char(' ')?; - self.spaced = true; - } - }; - } - if ty == TK_BLOB { - self.f.write_char('X')?; - self.f.write_char('\'')?; - if let Some(str) = value { - self.f.write_str(str)?; - } - return self.f.write_char('\''); - } else if let Some(str) = ty.as_str() { - self.f.write_str(str)?; - self.spaced = ty == TK_LP || ty == TK_DOT; // str should not be whitespace - } - if let Some(str) = value { - // trick for pretty-print - self.spaced = str.bytes().all(|b| b.is_ascii_whitespace()); - /*if !self.spaced { - self.f.write_char(' ')?; - }*/ - self.f.write_str(str) - } else { - Ok(()) - } + fn get_column_name(&self, _table_id: TableInternalId, _col_idx: usize) -> Option<&str> { + None } } -struct WriteTokenStream<'a, T: fmt::Write> { +pub struct WriteTokenStream<'a, T: Write> { write: &'a mut T, spaced: bool, } -impl TokenStream for WriteTokenStream<'_, T> { - type Error = fmt::Error; +impl<'a, T: Write> WriteTokenStream<'a, T> { + /// Create a new token stream writing to the specified writer + pub fn new(write: &'a mut T) -> Self { + Self { + write, + spaced: true, + } + } +} - fn append(&mut self, ty: TokenType, value: Option<&str>) -> fmt::Result { +impl TokenStream for WriteTokenStream<'_, T> { + type Error = Error; + + fn append(&mut self, ty: TokenType, value: Option<&str>) -> Result<()> { if !self.spaced { match ty { TK_COMMA | TK_SEMI | TK_RP | TK_DOT => {} @@ -77,45 +52,50 @@ impl TokenStream for WriteTokenStream<'_, T> { } }; } - if ty == TK_BLOB { - self.write.write_char('X')?; - self.write.write_char('\'')?; - if let Some(str) = value { - self.write.write_str(str)?; + + match (ty, ty.as_str(), value) { + (TK_BLOB, None, value) => { + self.write.write_char('X')?; + self.write.write_char('\'')?; + if let Some(str) = value { + self.write.write_str(str)?; + } + self.write.write_char('\'')?; + Ok(()) + } + (_, None, None) => Err(Error::Custom( + "can not format both none ty and none value".to_string(), + )), + (_, ty_str, value) => { + if let Some(str) = ty_str { + self.write.write_str(str)?; + self.spaced = ty == TK_LP || ty == TK_DOT; // str should not be whitespace + } + + if let Some(str) = value { + // trick for pretty-print + self.spaced = str.bytes().all(|b| b.is_ascii_whitespace()); + self.write.write_str(str)?; + } + + Ok(()) } - return self.write.write_char('\''); - } else if let Some(str) = ty.as_str() { - self.write.write_str(str)?; - self.spaced = ty == TK_LP || ty == TK_DOT; // str should not be whitespace - } - if let Some(str) = value { - // trick for pretty-print - self.spaced = str.bytes().all(|b| b.is_ascii_whitespace()); - self.write.write_str(str) - } else { - Ok(()) } } } -struct BlankContext; +pub struct BlankContext; -impl ToSqlContext for BlankContext { - fn get_column_name(&self, _table_id: crate::ast::TableInternalId, _col_idx: usize) -> String { - "".to_string() - } - - fn get_table_name(&self, _id: crate::ast::TableInternalId) -> &str { - "" - } -} +impl ToSqlContext for BlankContext {} /// Stream of token pub trait TokenStream { /// Potential error raised type Error; + /// Push token to this stream fn append(&mut self, ty: TokenType, value: Option<&str>) -> Result<(), Self::Error>; + /// Interspace iterator with commas fn comma(&mut self, items: I, context: &C) -> Result<(), Self::Error> where @@ -127,72 +107,89 @@ pub trait TokenStream { if i != 0 { self.append(TK_COMMA, None)?; } - item.to_tokens_with_context(self, context)?; + item.to_tokens(self, context)?; } Ok(()) } } +pub struct SqlDisplayer<'a, 'b, C: ToSqlContext, T: ToTokens> { + ctx: &'a C, + start_node: &'b T, +} + +impl<'a, 'b, C: ToSqlContext, T: ToTokens> SqlDisplayer<'a, 'b, C, T> { + /// Create a new displayer with the specified context and AST node + pub fn new(ctx: &'a C, start_node: &'b T) -> Self { + Self { ctx, start_node } + } + + // Return string representation with context + pub fn to_string(&self) -> Result { + let mut s = String::new(); + let mut stream = WriteTokenStream::new(&mut s); + self.start_node.to_tokens(&mut stream, self.ctx)?; + Ok(s) + } +} + +impl<'a, 'b, C: ToSqlContext, T: ToTokens> Display for SqlDisplayer<'a, 'b, C, T> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let mut stream = WriteTokenStream::new(f); + self.start_node + .to_tokens(&mut stream, self.ctx) + .map_err(|_| fmt::Error) + } +} + /// Generate token(s) from AST node pub trait ToTokens { /// Send token(s) to the specified stream with context - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error>; - /// Send token(s) to the specified stream - fn to_tokens(&self, s: &mut S) -> Result<(), S::Error> { - self.to_tokens_with_context(s, &BlankContext) + // Return displayer representation with context + fn displayer<'a, 'b, C: ToSqlContext>(&'b self, ctx: &'a C) -> SqlDisplayer<'a, 'b, C, Self> + where + Self: Sized, + { + SqlDisplayer::new(ctx, self) } - /// Format AST node - fn to_fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - self.to_fmt_with_context(f, &BlankContext) - } - - /// Format AST node with context - fn to_fmt_with_context( - &self, - f: &mut Formatter<'_>, - context: &C, - ) -> fmt::Result { - let mut s = FmtTokenStream { f, spaced: true }; - self.to_tokens_with_context(&mut s, context) - } - - /// Format AST node to string - fn format(&self) -> Result { - self.format_with_context(&BlankContext) - } - - /// Format AST node to string with context - fn format_with_context(&self, context: &C) -> Result { - let mut s = String::new(); - let mut w = WriteTokenStream { - write: &mut s, - spaced: true, - }; - - self.to_tokens_with_context(&mut w, context)?; - - Ok(s) + // Return string representation with blank context + fn format(&self) -> Result + where + Self: Sized, + { + self.displayer(&BlankContext).to_string() } } impl ToTokens for &T { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - ToTokens::to_tokens_with_context(&**self, s, context) + ToTokens::to_tokens(&**self, s, context) + } +} + +impl ToTokens for Box { + fn to_tokens( + &self, + s: &mut S, + context: &C, + ) -> Result<(), S::Error> { + ToTokens::to_tokens(self.as_ref(), s, context) } } impl ToTokens for String { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -202,7 +199,7 @@ impl ToTokens for String { } impl ToTokens for Cmd { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -210,16 +207,16 @@ impl ToTokens for Cmd { match self { Self::Explain(stmt) => { s.append(TK_EXPLAIN, None)?; - stmt.to_tokens_with_context(s, context)?; + stmt.to_tokens(s, context)?; } Self::ExplainQueryPlan(stmt) => { s.append(TK_EXPLAIN, None)?; s.append(TK_QUERY, None)?; s.append(TK_PLAN, None)?; - stmt.to_tokens_with_context(s, context)?; + stmt.to_tokens(s, context)?; } Self::Stmt(stmt) => { - stmt.to_tokens_with_context(s, context)?; + stmt.to_tokens(s, context)?; } } s.append(TK_SEMI, None) @@ -228,12 +225,12 @@ impl ToTokens for Cmd { impl Display for Cmd { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - self.to_fmt(f) + self.displayer(&BlankContext).fmt(f) } } impl ToTokens for Stmt { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -242,35 +239,35 @@ impl ToTokens for Stmt { Self::AlterTable(AlterTable { name, body }) => { s.append(TK_ALTER, None)?; s.append(TK_TABLE, None)?; - name.to_tokens_with_context(s, context)?; - body.to_tokens_with_context(s, context) + name.to_tokens(s, context)?; + body.to_tokens(s, context) } Self::Analyze { name } => { s.append(TK_ANALYZE, None)?; if let Some(name) = name { - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; } Ok(()) } Self::Attach { expr, db_name, key } => { s.append(TK_ATTACH, None)?; - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; s.append(TK_AS, None)?; - db_name.to_tokens_with_context(s, context)?; + db_name.to_tokens(s, context)?; if let Some(key) = key { s.append(TK_KEY, None)?; - key.to_tokens_with_context(s, context)?; + key.to_tokens(s, context)?; } Ok(()) } Self::Begin { typ, name } => { s.append(TK_BEGIN, None)?; if let Some(typ) = typ { - typ.to_tokens_with_context(s, context)?; + typ.to_tokens(s, context)?; } if let Some(name) = name { s.append(TK_TRANSACTION, None)?; - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; } Ok(()) } @@ -278,7 +275,7 @@ impl ToTokens for Stmt { s.append(TK_COMMIT, None)?; if let Some(name) = name { s.append(TK_TRANSACTION, None)?; - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; } Ok(()) } @@ -300,15 +297,15 @@ impl ToTokens for Stmt { s.append(TK_NOT, None)?; s.append(TK_EXISTS, None)?; } - idx_name.to_tokens_with_context(s, context)?; + idx_name.to_tokens(s, context)?; s.append(TK_ON, None)?; - tbl_name.to_tokens_with_context(s, context)?; + tbl_name.to_tokens(s, context)?; s.append(TK_LP, None)?; comma(columns, s, context)?; s.append(TK_RP, None)?; if let Some(where_clause) = where_clause { s.append(TK_WHERE, None)?; - where_clause.to_tokens_with_context(s, context)?; + where_clause.to_tokens(s, context)?; } Ok(()) } @@ -328,8 +325,8 @@ impl ToTokens for Stmt { s.append(TK_NOT, None)?; s.append(TK_EXISTS, None)?; } - tbl_name.to_tokens_with_context(s, context)?; - body.to_tokens_with_context(s, context) + tbl_name.to_tokens(s, context)?; + body.to_tokens(s, context) } Self::CreateTrigger { temporary, @@ -352,13 +349,13 @@ impl ToTokens for Stmt { s.append(TK_NOT, None)?; s.append(TK_EXISTS, None)?; } - trigger_name.to_tokens_with_context(s, context)?; + trigger_name.to_tokens(s, context)?; if let Some(time) = time { - time.to_tokens_with_context(s, context)?; + time.to_tokens(s, context)?; } - event.to_tokens_with_context(s, context)?; + event.to_tokens(s, context)?; s.append(TK_ON, None)?; - tbl_name.to_tokens_with_context(s, context)?; + tbl_name.to_tokens(s, context)?; if *for_each_row { s.append(TK_FOR, None)?; s.append(TK_EACH, None)?; @@ -366,11 +363,11 @@ impl ToTokens for Stmt { } if let Some(when_clause) = when_clause { s.append(TK_WHEN, None)?; - when_clause.to_tokens_with_context(s, context)?; + when_clause.to_tokens(s, context)?; } s.append(TK_BEGIN, Some("\n"))?; for command in commands { - command.to_tokens_with_context(s, context)?; + command.to_tokens(s, context)?; s.append(TK_SEMI, Some("\n"))?; } s.append(TK_END, None) @@ -392,14 +389,14 @@ impl ToTokens for Stmt { s.append(TK_NOT, None)?; s.append(TK_EXISTS, None)?; } - view_name.to_tokens_with_context(s, context)?; + view_name.to_tokens(s, context)?; if !columns.is_empty() { s.append(TK_LP, None)?; comma(columns, s, context)?; s.append(TK_RP, None)?; } s.append(TK_AS, None)?; - select.to_tokens_with_context(s, context) + select.to_tokens(s, context) } Self::CreateMaterializedView { if_not_exists, @@ -415,14 +412,14 @@ impl ToTokens for Stmt { s.append(TK_NOT, None)?; s.append(TK_EXISTS, None)?; } - view_name.to_tokens_with_context(s, context)?; + view_name.to_tokens(s, context)?; if !columns.is_empty() { s.append(TK_LP, None)?; comma(columns, s, context)?; s.append(TK_RP, None)?; } s.append(TK_AS, None)?; - select.to_tokens_with_context(s, context) + select.to_tokens(s, context) } Self::CreateVirtualTable(CreateVirtualTable { if_not_exists, @@ -438,9 +435,9 @@ impl ToTokens for Stmt { s.append(TK_NOT, None)?; s.append(TK_EXISTS, None)?; } - tbl_name.to_tokens_with_context(s, context)?; + tbl_name.to_tokens(s, context)?; s.append(TK_USING, None)?; - module_name.to_tokens_with_context(s, context)?; + module_name.to_tokens(s, context)?; s.append(TK_LP, None)?; if !args.is_empty() { comma(args, s, context)?; @@ -457,17 +454,17 @@ impl ToTokens for Stmt { limit, } => { if let Some(with) = with { - with.to_tokens_with_context(s, context)?; + with.to_tokens(s, context)?; } s.append(TK_DELETE, None)?; s.append(TK_FROM, None)?; - tbl_name.to_tokens_with_context(s, context)?; + tbl_name.to_tokens(s, context)?; if let Some(indexed) = indexed { - indexed.to_tokens_with_context(s, context)?; + indexed.to_tokens(s, context)?; } if let Some(where_clause) = where_clause { s.append(TK_WHERE, None)?; - where_clause.to_tokens_with_context(s, context)?; + where_clause.to_tokens(s, context)?; } if !returning.is_empty() { s.append(TK_RETURNING, None)?; @@ -479,13 +476,13 @@ impl ToTokens for Stmt { comma(order_by, s, context)?; } if let Some(limit) = limit { - limit.to_tokens_with_context(s, context)?; + limit.to_tokens(s, context)?; } Ok(()) } Self::Detach { name } => { s.append(TK_DETACH, None)?; - name.to_tokens_with_context(s, context) + name.to_tokens(s, context) } Self::DropIndex { if_exists, @@ -497,7 +494,7 @@ impl ToTokens for Stmt { s.append(TK_IF, None)?; s.append(TK_EXISTS, None)?; } - idx_name.to_tokens_with_context(s, context) + idx_name.to_tokens(s, context) } Self::DropTable { if_exists, @@ -509,7 +506,7 @@ impl ToTokens for Stmt { s.append(TK_IF, None)?; s.append(TK_EXISTS, None)?; } - tbl_name.to_tokens_with_context(s, context) + tbl_name.to_tokens(s, context) } Self::DropTrigger { if_exists, @@ -521,7 +518,7 @@ impl ToTokens for Stmt { s.append(TK_IF, None)?; s.append(TK_EXISTS, None)?; } - trigger_name.to_tokens_with_context(s, context) + trigger_name.to_tokens(s, context) } Self::DropView { if_exists, @@ -533,7 +530,7 @@ impl ToTokens for Stmt { s.append(TK_IF, None)?; s.append(TK_EXISTS, None)?; } - view_name.to_tokens_with_context(s, context) + view_name.to_tokens(s, context) } Self::Insert { with, @@ -544,7 +541,7 @@ impl ToTokens for Stmt { returning, } => { if let Some(with) = with { - with.to_tokens_with_context(s, context)?; + with.to_tokens(s, context)?; } if let Some(ResolveType::Replace) = or_conflict { s.append(TK_REPLACE, None)?; @@ -552,17 +549,17 @@ impl ToTokens for Stmt { s.append(TK_INSERT, None)?; if let Some(or_conflict) = or_conflict { s.append(TK_OR, None)?; - or_conflict.to_tokens_with_context(s, context)?; + or_conflict.to_tokens(s, context)?; } } s.append(TK_INTO, None)?; - tbl_name.to_tokens_with_context(s, context)?; + tbl_name.to_tokens(s, context)?; if !columns.is_empty() { s.append(TK_LP, None)?; comma(columns, s, context)?; s.append(TK_RP, None)?; } - body.to_tokens_with_context(s, context)?; + body.to_tokens(s, context)?; if !returning.is_empty() { s.append(TK_RETURNING, None)?; comma(returning, s, context)?; @@ -571,22 +568,22 @@ impl ToTokens for Stmt { } Self::Pragma { name, body } => { s.append(TK_PRAGMA, None)?; - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; if let Some(body) = body { - body.to_tokens_with_context(s, context)?; + body.to_tokens(s, context)?; } Ok(()) } Self::Reindex { name } => { s.append(TK_REINDEX, None)?; if let Some(name) = name { - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; } Ok(()) } Self::Release { name } => { s.append(TK_RELEASE, None)?; - name.to_tokens_with_context(s, context) + name.to_tokens(s, context) } Self::Rollback { tx_name, @@ -595,19 +592,19 @@ impl ToTokens for Stmt { s.append(TK_ROLLBACK, None)?; if let Some(tx_name) = tx_name { s.append(TK_TRANSACTION, None)?; - tx_name.to_tokens_with_context(s, context)?; + tx_name.to_tokens(s, context)?; } if let Some(savepoint_name) = savepoint_name { s.append(TK_TO, None)?; - savepoint_name.to_tokens_with_context(s, context)?; + savepoint_name.to_tokens(s, context)?; } Ok(()) } Self::Savepoint { name } => { s.append(TK_SAVEPOINT, None)?; - name.to_tokens_with_context(s, context) + name.to_tokens(s, context) } - Self::Select(select) => select.to_tokens_with_context(s, context), + Self::Select(select) => select.to_tokens(s, context), Self::Update(Update { with, or_conflict, @@ -621,26 +618,26 @@ impl ToTokens for Stmt { limit, }) => { if let Some(with) = with { - with.to_tokens_with_context(s, context)?; + with.to_tokens(s, context)?; } s.append(TK_UPDATE, None)?; if let Some(or_conflict) = or_conflict { s.append(TK_OR, None)?; - or_conflict.to_tokens_with_context(s, context)?; + or_conflict.to_tokens(s, context)?; } - tbl_name.to_tokens_with_context(s, context)?; + tbl_name.to_tokens(s, context)?; if let Some(indexed) = indexed { - indexed.to_tokens_with_context(s, context)?; + indexed.to_tokens(s, context)?; } s.append(TK_SET, None)?; comma(sets, s, context)?; if let Some(from) = from { s.append(TK_FROM, None)?; - from.to_tokens_with_context(s, context)?; + from.to_tokens(s, context)?; } if let Some(where_clause) = where_clause { s.append(TK_WHERE, None)?; - where_clause.to_tokens_with_context(s, context)?; + where_clause.to_tokens(s, context)?; } if !returning.is_empty() { s.append(TK_RETURNING, None)?; @@ -652,18 +649,18 @@ impl ToTokens for Stmt { comma(order_by, s, context)?; } if let Some(limit) = limit { - limit.to_tokens_with_context(s, context)?; + limit.to_tokens(s, context)?; } Ok(()) } Self::Vacuum { name, into } => { s.append(TK_VACUUM, None)?; if let Some(ref name) = name { - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; } if let Some(ref into) = into { s.append(TK_INTO, None)?; - into.to_tokens_with_context(s, context)?; + into.to_tokens(s, context)?; } Ok(()) } @@ -671,18 +668,8 @@ impl ToTokens for Stmt { } } -impl ToTokens for Box { - fn to_tokens_with_context( - &self, - s: &mut S, - context: &C, - ) -> Result<(), S::Error> { - self.as_ref().to_tokens_with_context(s, context) - } -} - impl ToTokens for Expr { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -694,19 +681,19 @@ impl ToTokens for Expr { start, end, } => { - lhs.to_tokens_with_context(s, context)?; + lhs.to_tokens(s, context)?; if *not { s.append(TK_NOT, None)?; } s.append(TK_BETWEEN, None)?; - start.to_tokens_with_context(s, context)?; + start.to_tokens(s, context)?; s.append(TK_AND, None)?; - end.to_tokens_with_context(s, context) + end.to_tokens(s, context) } Self::Binary(lhs, op, rhs) => { - lhs.to_tokens_with_context(s, context)?; - op.to_tokens_with_context(s, context)?; - rhs.to_tokens_with_context(s, context) + lhs.to_tokens(s, context)?; + op.to_tokens(s, context)?; + rhs.to_tokens(s, context) } Self::Case { base, @@ -715,46 +702,46 @@ impl ToTokens for Expr { } => { s.append(TK_CASE, None)?; if let Some(ref base) = base { - base.to_tokens_with_context(s, context)?; + base.to_tokens(s, context)?; } for (when, then) in when_then_pairs { s.append(TK_WHEN, None)?; - when.to_tokens_with_context(s, context)?; + when.to_tokens(s, context)?; s.append(TK_THEN, None)?; - then.to_tokens_with_context(s, context)?; + then.to_tokens(s, context)?; } if let Some(ref else_expr) = else_expr { s.append(TK_ELSE, None)?; - else_expr.to_tokens_with_context(s, context)?; + else_expr.to_tokens(s, context)?; } s.append(TK_END, None) } Self::Cast { expr, type_name } => { s.append(TK_CAST, None)?; s.append(TK_LP, None)?; - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; s.append(TK_AS, None)?; if let Some(ref type_name) = type_name { - type_name.to_tokens_with_context(s, context)?; + type_name.to_tokens(s, context)?; } s.append(TK_RP, None) } Self::Collate(expr, collation) => { - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; s.append(TK_COLLATE, None)?; double_quote(collation.as_str(), s) } Self::DoublyQualified(db_name, tbl_name, col_name) => { - db_name.to_tokens_with_context(s, context)?; + db_name.to_tokens(s, context)?; s.append(TK_DOT, None)?; - tbl_name.to_tokens_with_context(s, context)?; + tbl_name.to_tokens(s, context)?; s.append(TK_DOT, None)?; - col_name.to_tokens_with_context(s, context) + col_name.to_tokens(s, context) } Self::Exists(subquery) => { s.append(TK_EXISTS, None)?; s.append(TK_LP, None)?; - subquery.to_tokens_with_context(s, context)?; + subquery.to_tokens(s, context)?; s.append(TK_RP, None) } Self::FunctionCall { @@ -764,10 +751,10 @@ impl ToTokens for Expr { order_by, filter_over, } => { - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; s.append(TK_LP, None)?; if let Some(distinctness) = distinctness { - distinctness.to_tokens_with_context(s, context)?; + distinctness.to_tokens(s, context)?; } if !args.is_empty() { comma(args, s, context)?; @@ -778,25 +765,25 @@ impl ToTokens for Expr { comma(order_by, s, context)?; } s.append(TK_RP, None)?; - filter_over.to_tokens_with_context(s, context)?; + filter_over.to_tokens(s, context)?; Ok(()) } Self::FunctionCallStar { name, filter_over } => { - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; s.append(TK_LP, None)?; s.append(TK_STAR, None)?; s.append(TK_RP, None)?; - filter_over.to_tokens_with_context(s, context)?; + filter_over.to_tokens(s, context)?; Ok(()) } - Self::Id(id) => id.to_tokens_with_context(s, context), + Self::Id(id) => id.to_tokens(s, context), Self::Column { table, column, .. } => { - s.append(TK_ID, Some(context.get_table_name(*table)))?; + s.append(TK_ID, context.get_table_name(*table))?; s.append(TK_DOT, None)?; - s.append(TK_ID, Some(&context.get_column_name(*table, *column))) + s.append(TK_ID, context.get_column_name(*table, *column)) } Self::InList { lhs, not, rhs } => { - lhs.to_tokens_with_context(s, context)?; + lhs.to_tokens(s, context)?; if *not { s.append(TK_NOT, None)?; } @@ -808,13 +795,13 @@ impl ToTokens for Expr { s.append(TK_RP, None) } Self::InSelect { lhs, not, rhs } => { - lhs.to_tokens_with_context(s, context)?; + lhs.to_tokens(s, context)?; if *not { s.append(TK_NOT, None)?; } s.append(TK_IN, None)?; s.append(TK_LP, None)?; - rhs.to_tokens_with_context(s, context)?; + rhs.to_tokens(s, context)?; s.append(TK_RP, None) } Self::InTable { @@ -823,12 +810,12 @@ impl ToTokens for Expr { rhs, args, } => { - lhs.to_tokens_with_context(s, context)?; + lhs.to_tokens(s, context)?; if *not { s.append(TK_NOT, None)?; } s.append(TK_IN, None)?; - rhs.to_tokens_with_context(s, context)?; + rhs.to_tokens(s, context)?; if !args.is_empty() { s.append(TK_LP, None)?; comma(args, s, context)?; @@ -837,7 +824,7 @@ impl ToTokens for Expr { Ok(()) } Self::IsNull(sub_expr) => { - sub_expr.to_tokens_with_context(s, context)?; + sub_expr.to_tokens(s, context)?; s.append(TK_ISNULL, None) } Self::Like { @@ -847,22 +834,22 @@ impl ToTokens for Expr { rhs, escape, } => { - lhs.to_tokens_with_context(s, context)?; + lhs.to_tokens(s, context)?; if *not { s.append(TK_NOT, None)?; } - op.to_tokens_with_context(s, context)?; - rhs.to_tokens_with_context(s, context)?; + op.to_tokens(s, context)?; + rhs.to_tokens(s, context)?; if let Some(escape) = escape { s.append(TK_ESCAPE, None)?; - escape.to_tokens_with_context(s, context)?; + escape.to_tokens(s, context)?; } Ok(()) } - Self::Literal(lit) => lit.to_tokens_with_context(s, context), - Self::Name(name) => name.to_tokens_with_context(s, context), + Self::Literal(lit) => lit.to_tokens(s, context), + Self::Name(name) => name.to_tokens(s, context), Self::NotNull(sub_expr) => { - sub_expr.to_tokens_with_context(s, context)?; + sub_expr.to_tokens(s, context)?; s.append(TK_NOTNULL, None) } Self::Parenthesized(exprs) => { @@ -871,29 +858,29 @@ impl ToTokens for Expr { s.append(TK_RP, None) } Self::Qualified(qualifier, qualified) => { - qualifier.to_tokens_with_context(s, context)?; + qualifier.to_tokens(s, context)?; s.append(TK_DOT, None)?; - qualified.to_tokens_with_context(s, context) + qualified.to_tokens(s, context) } Self::Raise(rt, err) => { s.append(TK_RAISE, None)?; s.append(TK_LP, None)?; - rt.to_tokens_with_context(s, context)?; + rt.to_tokens(s, context)?; if let Some(err) = err { s.append(TK_COMMA, None)?; - err.to_tokens_with_context(s, context)?; + err.to_tokens(s, context)?; } s.append(TK_RP, None) } Self::RowId { .. } => Ok(()), Self::Subquery(query) => { s.append(TK_LP, None)?; - query.to_tokens_with_context(s, context)?; + query.to_tokens(s, context)?; s.append(TK_RP, None) } Self::Unary(op, sub_expr) => { - op.to_tokens_with_context(s, context)?; - sub_expr.to_tokens_with_context(s, context) + op.to_tokens(s, context)?; + sub_expr.to_tokens(s, context) } Self::Variable(var) => match var.chars().next() { Some(c) if c == '$' || c == '@' || c == '#' || c == ':' => { @@ -908,12 +895,12 @@ impl ToTokens for Expr { impl Display for Expr { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - self.to_fmt(f) + self.displayer(&BlankContext).fmt(f) } } impl ToTokens for Literal { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -932,7 +919,7 @@ impl ToTokens for Literal { } impl ToTokens for LikeOperator { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -950,7 +937,7 @@ impl ToTokens for LikeOperator { } impl ToTokens for Operator { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -987,7 +974,7 @@ impl ToTokens for Operator { } impl ToTokens for UnaryOperator { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -1005,54 +992,54 @@ impl ToTokens for UnaryOperator { } impl ToTokens for Select { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { if let Some(ref with) = self.with { - with.to_tokens_with_context(s, context)?; + with.to_tokens(s, context)?; } - self.body.to_tokens_with_context(s, context)?; + self.body.to_tokens(s, context)?; if !self.order_by.is_empty() { s.append(TK_ORDER, None)?; s.append(TK_BY, None)?; comma(&self.order_by, s, context)?; } if let Some(ref limit) = self.limit { - limit.to_tokens_with_context(s, context)?; + limit.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for SelectBody { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - self.select.to_tokens_with_context(s, context)?; + self.select.to_tokens(s, context)?; for compound in &self.compounds { - compound.to_tokens_with_context(s, context)?; + compound.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for CompoundSelect { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - self.operator.to_tokens_with_context(s, context)?; - self.select.to_tokens_with_context(s, context) + self.operator.to_tokens(s, context)?; + self.select.to_tokens(s, context) } } impl ToTokens for CompoundOperator { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -1071,12 +1058,12 @@ impl ToTokens for CompoundOperator { impl Display for CompoundOperator { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - self.to_fmt(f) + self.displayer(&BlankContext).fmt(f) } } impl ToTokens for OneSelect { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1092,19 +1079,19 @@ impl ToTokens for OneSelect { } => { s.append(TK_SELECT, None)?; if let Some(ref distinctness) = distinctness { - distinctness.to_tokens_with_context(s, context)?; + distinctness.to_tokens(s, context)?; } comma(columns, s, context)?; if let Some(ref from) = from { s.append(TK_FROM, None)?; - from.to_tokens_with_context(s, context)?; + from.to_tokens(s, context)?; } if let Some(ref where_clause) = where_clause { s.append(TK_WHERE, None)?; - where_clause.to_tokens_with_context(s, context)?; + where_clause.to_tokens(s, context)?; } if let Some(ref group_by) = group_by { - group_by.to_tokens_with_context(s, context)?; + group_by.to_tokens(s, context)?; } if !window_clause.is_empty() { s.append(TK_WINDOW, None)?; @@ -1130,14 +1117,14 @@ impl ToTokens for OneSelect { } impl ToTokens for FromClause { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - self.select.as_ref().to_tokens_with_context(s, context)?; + self.select.as_ref().to_tokens(s, context)?; for join in &self.joins { - join.to_tokens_with_context(s, context)?; + join.to_tokens(s, context)?; } Ok(()) @@ -1145,7 +1132,7 @@ impl ToTokens for FromClause { } impl ToTokens for Distinctness { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -1161,22 +1148,22 @@ impl ToTokens for Distinctness { } impl ToTokens for ResultColumn { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { match self { Self::Expr(expr, alias) => { - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; if let Some(alias) = alias { - alias.to_tokens_with_context(s, context)?; + alias.to_tokens(s, context)?; } Ok(()) } Self::Star => s.append(TK_STAR, None), Self::TableStar(tbl_name) => { - tbl_name.to_tokens_with_context(s, context)?; + tbl_name.to_tokens(s, context)?; s.append(TK_DOT, None)?; s.append(TK_STAR, None) } @@ -1185,7 +1172,7 @@ impl ToTokens for ResultColumn { } impl ToTokens for As { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1193,70 +1180,70 @@ impl ToTokens for As { match self { Self::As(ref name) => { s.append(TK_AS, None)?; - name.to_tokens_with_context(s, context) + name.to_tokens(s, context) } - Self::Elided(ref name) => name.to_tokens_with_context(s, context), + Self::Elided(ref name) => name.to_tokens(s, context), } } } impl ToTokens for JoinedSelectTable { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - self.operator.to_tokens_with_context(s, context)?; - self.table.to_tokens_with_context(s, context)?; + self.operator.to_tokens(s, context)?; + self.table.to_tokens(s, context)?; if let Some(ref constraint) = self.constraint { - constraint.to_tokens_with_context(s, context)?; + constraint.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for SelectTable { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { match self { Self::Table(name, alias, indexed) => { - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; if let Some(alias) = alias { - alias.to_tokens_with_context(s, context)?; + alias.to_tokens(s, context)?; } if let Some(indexed) = indexed { - indexed.to_tokens_with_context(s, context)?; + indexed.to_tokens(s, context)?; } Ok(()) } Self::TableCall(name, exprs, alias) => { - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; s.append(TK_LP, None)?; comma(exprs, s, context)?; s.append(TK_RP, None)?; if let Some(alias) = alias { - alias.to_tokens_with_context(s, context)?; + alias.to_tokens(s, context)?; } Ok(()) } Self::Select(select, alias) => { s.append(TK_LP, None)?; - select.to_tokens_with_context(s, context)?; + select.to_tokens(s, context)?; s.append(TK_RP, None)?; if let Some(alias) = alias { - alias.to_tokens_with_context(s, context)?; + alias.to_tokens(s, context)?; } Ok(()) } Self::Sub(from, alias) => { s.append(TK_LP, None)?; - from.to_tokens_with_context(s, context)?; + from.to_tokens(s, context)?; s.append(TK_RP, None)?; if let Some(alias) = alias { - alias.to_tokens_with_context(s, context)?; + alias.to_tokens(s, context)?; } Ok(()) } @@ -1265,7 +1252,7 @@ impl ToTokens for SelectTable { } impl ToTokens for JoinOperator { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1274,7 +1261,7 @@ impl ToTokens for JoinOperator { Self::Comma => s.append(TK_COMMA, None), Self::TypedJoin(join_type) => { if let Some(ref join_type) = join_type { - join_type.to_tokens_with_context(s, context)?; + join_type.to_tokens(s, context)?; } s.append(TK_JOIN, None) } @@ -1283,7 +1270,7 @@ impl ToTokens for JoinOperator { } impl ToTokens for JoinType { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -1315,7 +1302,7 @@ impl ToTokens for JoinType { } impl ToTokens for JoinConstraint { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1323,7 +1310,7 @@ impl ToTokens for JoinConstraint { match self { Self::On(expr) => { s.append(TK_ON, None)?; - expr.to_tokens_with_context(s, context) + expr.to_tokens(s, context) } Self::Using(col_names) => { s.append(TK_USING, None)?; @@ -1336,7 +1323,7 @@ impl ToTokens for JoinConstraint { } impl ToTokens for GroupBy { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1346,14 +1333,14 @@ impl ToTokens for GroupBy { comma(&self.exprs, s, context)?; if let Some(ref having) = self.having { s.append(TK_HAVING, None)?; - having.to_tokens_with_context(s, context)?; + having.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for Name { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -1364,31 +1351,37 @@ impl ToTokens for Name { impl Display for Name { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - self.to_fmt(f) + self.displayer(&BlankContext).fmt(f) } } impl ToTokens for QualifiedName { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { if let Some(ref db_name) = self.db_name { - db_name.to_tokens_with_context(s, context)?; + db_name.to_tokens(s, context)?; s.append(TK_DOT, None)?; } - self.name.to_tokens_with_context(s, context)?; + self.name.to_tokens(s, context)?; if let Some(ref alias) = self.alias { s.append(TK_AS, None)?; - alias.to_tokens_with_context(s, context)?; + alias.to_tokens(s, context)?; } Ok(()) } } +impl Display for QualifiedName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.displayer(&BlankContext).fmt(f) + } +} + impl ToTokens for AlterTableBody { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1397,31 +1390,31 @@ impl ToTokens for AlterTableBody { Self::RenameTo(name) => { s.append(TK_RENAME, None)?; s.append(TK_TO, None)?; - name.to_tokens_with_context(s, context) + name.to_tokens(s, context) } Self::AddColumn(def) => { s.append(TK_ADD, None)?; s.append(TK_COLUMNKW, None)?; - def.to_tokens_with_context(s, context) + def.to_tokens(s, context) } Self::RenameColumn { old, new } => { s.append(TK_RENAME, None)?; s.append(TK_COLUMNKW, None)?; - old.to_tokens_with_context(s, context)?; + old.to_tokens(s, context)?; s.append(TK_TO, None)?; - new.to_tokens_with_context(s, context) + new.to_tokens(s, context) } Self::DropColumn(name) => { s.append(TK_DROP, None)?; s.append(TK_COLUMNKW, None)?; - name.to_tokens_with_context(s, context) + name.to_tokens(s, context) } } } } impl ToTokens for CreateTableBody { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1450,45 +1443,45 @@ impl ToTokens for CreateTableBody { } Self::AsSelect(select) => { s.append(TK_AS, None)?; - select.to_tokens_with_context(s, context) + select.to_tokens(s, context) } } } } impl ToTokens for ColumnDefinition { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - self.col_name.to_tokens_with_context(s, context)?; + self.col_name.to_tokens(s, context)?; if let Some(ref col_type) = self.col_type { - col_type.to_tokens_with_context(s, context)?; + col_type.to_tokens(s, context)?; } for constraint in &self.constraints { - constraint.to_tokens_with_context(s, context)?; + constraint.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for NamedColumnConstraint { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { if let Some(ref name) = self.name { s.append(TK_CONSTRAINT, None)?; - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; } - self.constraint.to_tokens_with_context(s, context) + self.constraint.to_tokens(s, context) } } impl ToTokens for ColumnConstraint { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1502,12 +1495,12 @@ impl ToTokens for ColumnConstraint { s.append(TK_PRIMARY, None)?; s.append(TK_KEY, None)?; if let Some(order) = order { - order.to_tokens_with_context(s, context)?; + order.to_tokens(s, context)?; } if let Some(conflict_clause) = conflict_clause { s.append(TK_ON, None)?; s.append(TK_CONFLICT, None)?; - conflict_clause.to_tokens_with_context(s, context)?; + conflict_clause.to_tokens(s, context)?; } if *auto_increment { s.append(TK_AUTOINCR, None)?; @@ -1525,7 +1518,7 @@ impl ToTokens for ColumnConstraint { if let Some(conflict_clause) = conflict_clause { s.append(TK_ON, None)?; s.append(TK_CONFLICT, None)?; - conflict_clause.to_tokens_with_context(s, context)?; + conflict_clause.to_tokens(s, context)?; } Ok(()) } @@ -1534,42 +1527,42 @@ impl ToTokens for ColumnConstraint { if let Some(conflict_clause) = conflict_clause { s.append(TK_ON, None)?; s.append(TK_CONFLICT, None)?; - conflict_clause.to_tokens_with_context(s, context)?; + conflict_clause.to_tokens(s, context)?; } Ok(()) } Self::Check(expr) => { s.append(TK_CHECK, None)?; s.append(TK_LP, None)?; - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; s.append(TK_RP, None) } Self::Default(expr) => { s.append(TK_DEFAULT, None)?; - expr.to_tokens_with_context(s, context) + expr.to_tokens(s, context) } Self::Collate { collation_name } => { s.append(TK_COLLATE, None)?; - collation_name.to_tokens_with_context(s, context) + collation_name.to_tokens(s, context) } Self::ForeignKey { clause, deref_clause, } => { s.append(TK_REFERENCES, None)?; - clause.to_tokens_with_context(s, context)?; + clause.to_tokens(s, context)?; if let Some(deref_clause) = deref_clause { - deref_clause.to_tokens_with_context(s, context)?; + deref_clause.to_tokens(s, context)?; } Ok(()) } Self::Generated { expr, typ } => { s.append(TK_AS, None)?; s.append(TK_LP, None)?; - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; s.append(TK_RP, None)?; if let Some(typ) = typ { - typ.to_tokens_with_context(s, context)?; + typ.to_tokens(s, context)?; } Ok(()) } @@ -1578,21 +1571,21 @@ impl ToTokens for ColumnConstraint { } impl ToTokens for NamedTableConstraint { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { if let Some(ref name) = self.name { s.append(TK_CONSTRAINT, None)?; - name.to_tokens_with_context(s, context)?; + name.to_tokens(s, context)?; } - self.constraint.to_tokens_with_context(s, context) + self.constraint.to_tokens(s, context) } } impl ToTokens for TableConstraint { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1614,7 +1607,7 @@ impl ToTokens for TableConstraint { if let Some(conflict_clause) = conflict_clause { s.append(TK_ON, None)?; s.append(TK_CONFLICT, None)?; - conflict_clause.to_tokens_with_context(s, context)?; + conflict_clause.to_tokens(s, context)?; } Ok(()) } @@ -1629,14 +1622,14 @@ impl ToTokens for TableConstraint { if let Some(conflict_clause) = conflict_clause { s.append(TK_ON, None)?; s.append(TK_CONFLICT, None)?; - conflict_clause.to_tokens_with_context(s, context)?; + conflict_clause.to_tokens(s, context)?; } Ok(()) } Self::Check(expr) => { s.append(TK_CHECK, None)?; s.append(TK_LP, None)?; - expr.to_tokens_with_context(s, context)?; + expr.to_tokens(s, context)?; s.append(TK_RP, None) } Self::ForeignKey { @@ -1650,9 +1643,9 @@ impl ToTokens for TableConstraint { comma(columns, s, context)?; s.append(TK_RP, None)?; s.append(TK_REFERENCES, None)?; - clause.to_tokens_with_context(s, context)?; + clause.to_tokens(s, context)?; if let Some(deref_clause) = deref_clause { - deref_clause.to_tokens_with_context(s, context)?; + deref_clause.to_tokens(s, context)?; } Ok(()) } @@ -1661,7 +1654,7 @@ impl ToTokens for TableConstraint { } impl ToTokens for SortOrder { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -1677,7 +1670,7 @@ impl ToTokens for SortOrder { } impl ToTokens for NullsOrder { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -1694,26 +1687,26 @@ impl ToTokens for NullsOrder { } impl ToTokens for ForeignKeyClause { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - self.tbl_name.to_tokens_with_context(s, context)?; + self.tbl_name.to_tokens(s, context)?; if !self.columns.is_empty() { s.append(TK_LP, None)?; comma(&self.columns, s, context)?; s.append(TK_RP, None)?; } for arg in &self.args { - arg.to_tokens_with_context(s, context)?; + arg.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for RefArg { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1722,28 +1715,28 @@ impl ToTokens for RefArg { Self::OnDelete(ref action) => { s.append(TK_ON, None)?; s.append(TK_DELETE, None)?; - action.to_tokens_with_context(s, context) + action.to_tokens(s, context) } Self::OnInsert(ref action) => { s.append(TK_ON, None)?; s.append(TK_INSERT, None)?; - action.to_tokens_with_context(s, context) + action.to_tokens(s, context) } Self::OnUpdate(ref action) => { s.append(TK_ON, None)?; s.append(TK_UPDATE, None)?; - action.to_tokens_with_context(s, context) + action.to_tokens(s, context) } Self::Match(ref name) => { s.append(TK_MATCH, None)?; - name.to_tokens_with_context(s, context) + name.to_tokens(s, context) } } } } impl ToTokens for RefAct { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -1768,7 +1761,7 @@ impl ToTokens for RefAct { } impl ToTokens for DeferSubclause { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1778,14 +1771,14 @@ impl ToTokens for DeferSubclause { } s.append(TK_DEFERRABLE, None)?; if let Some(init_deferred) = self.init_deferred { - init_deferred.to_tokens_with_context(s, context)?; + init_deferred.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for InitDeferredPred { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -1802,25 +1795,25 @@ impl ToTokens for InitDeferredPred { } impl ToTokens for IndexedColumn { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - self.col_name.to_tokens_with_context(s, context)?; + self.col_name.to_tokens(s, context)?; if let Some(ref collation_name) = self.collation_name { s.append(TK_COLLATE, None)?; - collation_name.to_tokens_with_context(s, context)?; + collation_name.to_tokens(s, context)?; } if let Some(order) = self.order { - order.to_tokens_with_context(s, context)?; + order.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for Indexed { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1829,7 +1822,7 @@ impl ToTokens for Indexed { Self::IndexedBy(ref name) => { s.append(TK_INDEXED, None)?; s.append(TK_BY, None)?; - name.to_tokens_with_context(s, context) + name.to_tokens(s, context) } Self::NotIndexed => { s.append(TK_NOT, None)?; @@ -1840,49 +1833,49 @@ impl ToTokens for Indexed { } impl ToTokens for SortedColumn { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - self.expr.to_tokens_with_context(s, context)?; + self.expr.to_tokens(s, context)?; if let Some(ref order) = self.order { - order.to_tokens_with_context(s, context)?; + order.to_tokens(s, context)?; } if let Some(ref nulls) = self.nulls { - nulls.to_tokens_with_context(s, context)?; + nulls.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for Limit { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { s.append(TK_LIMIT, None)?; - self.expr.to_tokens_with_context(s, context)?; + self.expr.to_tokens(s, context)?; if let Some(ref offset) = self.offset { s.append(TK_OFFSET, None)?; - offset.to_tokens_with_context(s, context)?; + offset.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for InsertBody { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { match self { Self::Select(select, upsert) => { - select.to_tokens_with_context(s, context)?; + select.to_tokens(s, context)?; if let Some(upsert) = upsert { - upsert.to_tokens_with_context(s, context)?; + upsert.to_tokens(s, context)?; } Ok(()) } @@ -1895,7 +1888,7 @@ impl ToTokens for InsertBody { } impl ToTokens for Set { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1908,12 +1901,12 @@ impl ToTokens for Set { s.append(TK_RP, None)?; } s.append(TK_EQ, None)?; - self.expr.to_tokens_with_context(s, context) + self.expr.to_tokens(s, context) } } impl ToTokens for PragmaBody { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1921,11 +1914,11 @@ impl ToTokens for PragmaBody { match self { Self::Equals(value) => { s.append(TK_EQ, None)?; - value.to_tokens_with_context(s, context) + value.to_tokens(s, context) } Self::Call(value) => { s.append(TK_LP, None)?; - value.to_tokens_with_context(s, context)?; + value.to_tokens(s, context)?; s.append(TK_RP, None) } } @@ -1933,7 +1926,7 @@ impl ToTokens for PragmaBody { } impl ToTokens for TriggerTime { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -1950,7 +1943,7 @@ impl ToTokens for TriggerTime { } impl ToTokens for TriggerEvent { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1969,7 +1962,7 @@ impl ToTokens for TriggerEvent { } impl ToTokens for TriggerCmd { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -1985,18 +1978,18 @@ impl ToTokens for TriggerCmd { s.append(TK_UPDATE, None)?; if let Some(or_conflict) = or_conflict { s.append(TK_OR, None)?; - or_conflict.to_tokens_with_context(s, context)?; + or_conflict.to_tokens(s, context)?; } - tbl_name.to_tokens_with_context(s, context)?; + tbl_name.to_tokens(s, context)?; s.append(TK_SET, None)?; comma(sets, s, context)?; if let Some(from) = from { s.append(TK_FROM, None)?; - from.to_tokens_with_context(s, context)?; + from.to_tokens(s, context)?; } if let Some(where_clause) = where_clause { s.append(TK_WHERE, None)?; - where_clause.to_tokens_with_context(s, context)?; + where_clause.to_tokens(s, context)?; } Ok(()) } @@ -2014,19 +2007,19 @@ impl ToTokens for TriggerCmd { s.append(TK_INSERT, None)?; if let Some(or_conflict) = or_conflict { s.append(TK_OR, None)?; - or_conflict.to_tokens_with_context(s, context)?; + or_conflict.to_tokens(s, context)?; } } s.append(TK_INTO, None)?; - tbl_name.to_tokens_with_context(s, context)?; + tbl_name.to_tokens(s, context)?; if !col_names.is_empty() { s.append(TK_LP, None)?; comma(col_names, s, context)?; s.append(TK_RP, None)?; } - select.to_tokens_with_context(s, context)?; + select.to_tokens(s, context)?; if let Some(upsert) = upsert { - upsert.to_tokens_with_context(s, context)?; + upsert.to_tokens(s, context)?; } if !returning.is_empty() { s.append(TK_RETURNING, None)?; @@ -2040,20 +2033,20 @@ impl ToTokens for TriggerCmd { } => { s.append(TK_DELETE, None)?; s.append(TK_FROM, None)?; - tbl_name.to_tokens_with_context(s, context)?; + tbl_name.to_tokens(s, context)?; if let Some(where_clause) = where_clause { s.append(TK_WHERE, None)?; - where_clause.to_tokens_with_context(s, context)?; + where_clause.to_tokens(s, context)?; } Ok(()) } - Self::Select(select) => select.to_tokens_with_context(s, context), + Self::Select(select) => select.to_tokens(s, context), } } } impl ToTokens for ResolveType { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -2072,7 +2065,7 @@ impl ToTokens for ResolveType { } impl ToTokens for With { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -2086,12 +2079,12 @@ impl ToTokens for With { } impl ToTokens for CommonTableExpr { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - self.tbl_name.to_tokens_with_context(s, context)?; + self.tbl_name.to_tokens(s, context)?; if !self.columns.is_empty() { s.append(TK_LP, None)?; comma(&self.columns, s, context)?; @@ -2109,13 +2102,13 @@ impl ToTokens for CommonTableExpr { } }; s.append(TK_LP, None)?; - self.select.to_tokens_with_context(s, context)?; + self.select.to_tokens(s, context)?; s.append(TK_RP, None) } } impl ToTokens for Type { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -2125,7 +2118,7 @@ impl ToTokens for Type { Some(ref size) => { s.append(TK_ID, Some(&self.name))?; // TODO check there is no forbidden chars s.append(TK_LP, None)?; - size.to_tokens_with_context(s, context)?; + size.to_tokens(s, context)?; s.append(TK_RP, None) } } @@ -2133,24 +2126,24 @@ impl ToTokens for Type { } impl ToTokens for TypeSize { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { match self { - Self::MaxSize(size) => size.to_tokens_with_context(s, context), + Self::MaxSize(size) => size.to_tokens(s, context), Self::TypeSize(size1, size2) => { - size1.to_tokens_with_context(s, context)?; + size1.to_tokens(s, context)?; s.append(TK_COMMA, None)?; - size2.to_tokens_with_context(s, context) + size2.to_tokens(s, context) } } } } impl ToTokens for TransactionType { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -2167,7 +2160,7 @@ impl ToTokens for TransactionType { } impl ToTokens for Upsert { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -2175,18 +2168,18 @@ impl ToTokens for Upsert { s.append(TK_ON, None)?; s.append(TK_CONFLICT, None)?; if let Some(ref index) = self.index { - index.to_tokens_with_context(s, context)?; + index.to_tokens(s, context)?; } - self.do_clause.to_tokens_with_context(s, context)?; + self.do_clause.to_tokens(s, context)?; if let Some(ref next) = self.next { - next.to_tokens_with_context(s, context)?; + next.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for UpsertIndex { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -2196,14 +2189,14 @@ impl ToTokens for UpsertIndex { s.append(TK_RP, None)?; if let Some(ref where_clause) = self.where_clause { s.append(TK_WHERE, None)?; - where_clause.to_tokens_with_context(s, context)?; + where_clause.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for UpsertDo { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -2216,7 +2209,7 @@ impl ToTokens for UpsertDo { comma(sets, s, context)?; if let Some(where_clause) = where_clause { s.append(TK_WHERE, None)?; - where_clause.to_tokens_with_context(s, context)?; + where_clause.to_tokens(s, context)?; } Ok(()) } @@ -2229,7 +2222,7 @@ impl ToTokens for UpsertDo { } impl ToTokens for FunctionTail { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -2238,51 +2231,51 @@ impl ToTokens for FunctionTail { s.append(TK_FILTER, None)?; s.append(TK_LP, None)?; s.append(TK_WHERE, None)?; - filter_clause.to_tokens_with_context(s, context)?; + filter_clause.to_tokens(s, context)?; s.append(TK_RP, None)?; } if let Some(ref over_clause) = self.over_clause { s.append(TK_OVER, None)?; - over_clause.to_tokens_with_context(s, context)?; + over_clause.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for Over { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { match self { - Self::Window(ref window) => window.to_tokens_with_context(s, context), - Self::Name(ref name) => name.to_tokens_with_context(s, context), + Self::Window(ref window) => window.to_tokens(s, context), + Self::Name(ref name) => name.to_tokens(s, context), } } } impl ToTokens for WindowDef { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - self.name.to_tokens_with_context(s, context)?; + self.name.to_tokens(s, context)?; s.append(TK_AS, None)?; - self.window.to_tokens_with_context(s, context) + self.window.to_tokens(s, context) } } impl ToTokens for Window { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { s.append(TK_LP, None)?; if let Some(ref base) = self.base { - base.to_tokens_with_context(s, context)?; + base.to_tokens(s, context)?; } if !self.partition_by.is_empty() { s.append(TK_PARTITION, None)?; @@ -2295,37 +2288,37 @@ impl ToTokens for Window { comma(&self.order_by, s, context)?; } if let Some(ref frame_clause) = self.frame_clause { - frame_clause.to_tokens_with_context(s, context)?; + frame_clause.to_tokens(s, context)?; } s.append(TK_RP, None) } } impl ToTokens for FrameClause { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, ) -> Result<(), S::Error> { - self.mode.to_tokens_with_context(s, context)?; + self.mode.to_tokens(s, context)?; if let Some(ref end) = self.end { s.append(TK_BETWEEN, None)?; - self.start.to_tokens_with_context(s, context)?; + self.start.to_tokens(s, context)?; s.append(TK_AND, None)?; - end.to_tokens_with_context(s, context)?; + end.to_tokens(s, context)?; } else { - self.start.to_tokens_with_context(s, context)?; + self.start.to_tokens(s, context)?; } if let Some(ref exclude) = self.exclude { s.append(TK_EXCLUDE, None)?; - exclude.to_tokens_with_context(s, context)?; + exclude.to_tokens(s, context)?; } Ok(()) } } impl ToTokens for FrameMode { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, @@ -2342,7 +2335,7 @@ impl ToTokens for FrameMode { } impl ToTokens for FrameBound { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, context: &C, @@ -2353,11 +2346,11 @@ impl ToTokens for FrameBound { s.append(TK_ROW, None) } Self::Following(value) => { - value.to_tokens_with_context(s, context)?; + value.to_tokens(s, context)?; s.append(TK_FOLLOWING, None) } Self::Preceding(value) => { - value.to_tokens_with_context(s, context)?; + value.to_tokens(s, context)?; s.append(TK_PRECEDING, None) } Self::UnboundedFollowing => { @@ -2373,7 +2366,7 @@ impl ToTokens for FrameBound { } impl ToTokens for FrameExclude { - fn to_tokens_with_context( + fn to_tokens( &self, s: &mut S, _: &C, diff --git a/parser/src/error.rs b/parser/src/error.rs index 27fe46956..23e0f4b4b 100644 --- a/parser/src/error.rs +++ b/parser/src/error.rs @@ -52,4 +52,7 @@ pub enum Error { // Custom error message #[error("{0}")] Custom(String), + // formatting error + #[error("{0}")] + FormatError(#[from] std::fmt::Error), } diff --git a/parser/src/parser.rs b/parser/src/parser.rs index 8d1f1e442..cc61ac8c1 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -326,7 +326,7 @@ impl<'a> Parser<'a> { */ match tok.token_type.unwrap() { TK_WINDOW => { - let can_be_window = self.try_parse(|p| { + let can_be_window = self.try_parse(|p| -> Result { match p.consume_lexer_without_whitespaces_or_comments() { None => return Ok(false), Some(tok) => match get_token(tok?.token_type.unwrap()) { @@ -352,7 +352,7 @@ impl<'a> Parser<'a> { let prev_tt = self.current_token.token_type.unwrap_or(TK_EOF); let can_be_over = { if prev_tt == TK_RP { - self.try_parse(|p| { + self.try_parse(|p| -> Result { match p.consume_lexer_without_whitespaces_or_comments() { None => Ok(false), Some(tok) => match get_token(tok?.token_type.unwrap()) { @@ -374,7 +374,7 @@ impl<'a> Parser<'a> { let prev_tt = self.current_token.token_type.unwrap_or(TK_EOF); let can_be_filter = { if prev_tt == TK_RP { - self.try_parse(|p| { + self.try_parse(|p| -> Result { match p.consume_lexer_without_whitespaces_or_comments() { None => Ok(false), Some(tok) => match tok?.token_type.unwrap() { @@ -393,7 +393,7 @@ impl<'a> Parser<'a> { } } TK_UNION => { - let can_be_union = self.try_parse(|p| { + let can_be_union = self.try_parse(|p| -> Result { match p.consume_lexer_without_whitespaces_or_comments() { None => Ok(false), Some(tok) => match tok?.token_type.unwrap() { @@ -408,7 +408,7 @@ impl<'a> Parser<'a> { } } TK_EXCEPT | TK_INTERSECT => { - let can_be_except = self.try_parse(|p| { + let can_be_except = self.try_parse(|p| -> Result { match p.consume_lexer_without_whitespaces_or_comments() { None => Ok(false), Some(tok) => match tok?.token_type.unwrap() { @@ -431,7 +431,7 @@ impl<'a> Parser<'a> { } } TK_GENERATED => { - let can_be_generated = self.try_parse(|p| { + let can_be_generated = self.try_parse(|p| -> Result { match p.consume_lexer_without_whitespaces_or_comments() { None => return Ok(false), Some(tok) => match tok?.token_type.unwrap() { @@ -456,7 +456,7 @@ impl<'a> Parser<'a> { TK_WITHOUT => { let prev_tt = self.current_token.token_type.unwrap_or(TK_EOF); let can_be_without = match prev_tt { - TK_RP | TK_COMMA => self.try_parse(|p| { + TK_RP | TK_COMMA => self.try_parse(|p| -> Result { match p.consume_lexer_without_whitespaces_or_comments() { None => Ok(false), Some(tok) => match get_token(tok?.token_type.unwrap()) { @@ -11396,14 +11396,25 @@ mod tests { ]; for (input, expected) in test_cases { - println!("Testing input: {:?}", from_bytes(input)); + let input_str = from_bytes(input); let parser = Parser::new(input); let mut results = Vec::new(); for cmd in parser { results.push(cmd.unwrap()); } - assert_eq!(results, expected, "Input: {input:?}"); + assert_eq!(results, expected, "Input: {input_str:?}"); + + use crate::ast::fmt::{BlankContext, ToTokens}; + // to_string tests + for (i, r) in results.iter().enumerate() { + let rstring = r.displayer(&BlankContext).to_string().unwrap(); + + // put new string into parser again + let result = Parser::new(rstring.as_bytes()).next().unwrap().unwrap(); + let expected = &expected[i]; + assert_eq!(result, expected.clone(), "Input: {rstring:?}"); + } } } } From 9e4f3b41ef8fbc1bdba4127710458326bcdeef2f Mon Sep 17 00:00:00 2001 From: TcMits Date: Sun, 24 Aug 2025 14:07:46 +0700 Subject: [PATCH 2/8] correctly implement get_column_name --- core/translate/display.rs | 7 ++----- core/translate/main_loop.rs | 21 ++++++++++++++------- parser/src/ast/fmt.rs | 24 ++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 14 deletions(-) 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)?; From d24812373fc073d2fbe89b96448079e8939e6963 Mon Sep 17 00:00:00 2001 From: TcMits Date: Sun, 24 Aug 2025 14:37:29 +0700 Subject: [PATCH 3/8] missing context for to_string --- core/translate/main_loop.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/core/translate/main_loop.rs b/core/translate/main_loop.rs index 51260715b..f190f3424 100644 --- a/core/translate/main_loop.rs +++ b/core/translate/main_loop.rs @@ -148,14 +148,21 @@ pub fn init_loop( agg.args.len() == 1, "DISTINCT aggregate functions must have exactly one argument" ); - let index_name = format!("distinct_agg_{}_{}", i, agg.args[0]); + let index_name = format!( + "distinct_agg_{}_{}", + i, + agg.args[0].displayer(&PlanContext(&[tables])) + ); let index = Arc::new(Index { name: index_name.clone(), table_name: String::new(), ephemeral: true, root_page: 0, columns: vec![IndexColumn { - name: agg.args[0].to_string(), + name: agg.args[0] + .displayer(&PlanContext(&[tables])) + .to_string() + .unwrap(), order: SortOrder::Asc, pos_in_table: 0, collation: None, // FIXME: this should be inferred from the expression From 3cd0ebe22f4e29129e678bf765a21b4f6fd64173 Mon Sep 17 00:00:00 2001 From: TcMits Date: Sun, 24 Aug 2025 14:40:48 +0700 Subject: [PATCH 4/8] clippy --- core/translate/display.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/core/translate/display.rs b/core/translate/display.rs index 25a5744f8..1bbb976f5 100644 --- a/core/translate/display.rs +++ b/core/translate/display.rs @@ -236,28 +236,20 @@ 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> { - let Some(table) = self + let table = self .0 .iter() - .find_map(|table_ref| table_ref.find_table_by_internal_id(table_id)) - else { - return None; - }; + .find_map(|table_ref| table_ref.find_table_by_internal_id(table_id))?; let cols = table.columns(); - match cols.get(col_idx) { - None => None, - Some(col) => Some(col.name.as_ref().map(|name| name.as_ref())), - } + cols.get(col_idx) + .map(|col| col.name.as_ref().map(|name| name.as_ref())) } fn get_table_name(&self, id: TableInternalId) -> Option<&str> { - let Some(table_ref) = self + let table_ref = self .0 .iter() - .find(|table_ref| table_ref.find_table_by_internal_id(id).is_some()) - else { - return None; - }; + .find(|table_ref| table_ref.find_table_by_internal_id(id).is_some())?; let joined_table = table_ref.find_joined_table_by_internal_id(id); let outer_query = table_ref.find_outer_query_ref_by_internal_id(id); match (joined_table, outer_query) { From 3cd43b9374d0a3f90d972e96e11065bc3696a4ae Mon Sep 17 00:00:00 2001 From: TcMits Date: Wed, 27 Aug 2025 13:22:40 +0700 Subject: [PATCH 5/8] no need to return error in fmt --- parser/src/ast/fmt.rs | 41 ++++++++++++++++++++++++----------------- parser/src/error.rs | 3 --- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/parser/src/ast/fmt.rs b/parser/src/ast/fmt.rs index b15cbb12a..224d942cf 100644 --- a/parser/src/ast/fmt.rs +++ b/parser/src/ast/fmt.rs @@ -2,7 +2,6 @@ use std::fmt::{self, Display, Formatter, Write}; use crate::ast::*; -use crate::error::Error; use crate::token::TokenType; use crate::token::TokenType::*; use crate::Result; @@ -26,15 +25,26 @@ pub trait ToSqlContext { 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, - } + // help function to handle missing table/column names + fn get_table_and_column_names( + &self, + table_id: TableInternalId, + col_idx: usize, + ) -> (String, String) { + let table_name = self + .get_table_name(table_id) + .map(|s| s.to_owned()) + .unwrap_or_else(|| format!("t{}", table_id.0)); + + let column_name = self + .get_column_name(table_id, col_idx) + .map(|opt| { + opt.map(|s| s.to_owned()) + .unwrap_or_else(|| format!("c{}", col_idx)) + }) + .unwrap_or_else(|| format!("c{}", col_idx)); + + (table_name, column_name) } } @@ -54,9 +64,9 @@ impl<'a, T: Write> WriteTokenStream<'a, T> { } impl TokenStream for WriteTokenStream<'_, T> { - type Error = Error; + type Error = fmt::Error; - fn append(&mut self, ty: TokenType, value: Option<&str>) -> Result<()> { + fn append(&mut self, ty: TokenType, value: Option<&str>) -> fmt::Result { if !self.spaced { match ty { TK_COMMA | TK_SEMI | TK_RP | TK_DOT => {} @@ -77,9 +87,6 @@ impl TokenStream for WriteTokenStream<'_, T> { self.write.write_char('\'')?; Ok(()) } - (_, None, None) => Err(Error::Custom( - "can not format both none ty and none value".to_string(), - )), (_, ty_str, value) => { if let Some(str) = ty_str { self.write.write_str(str)?; @@ -139,7 +146,7 @@ impl<'a, 'b, C: ToSqlContext, T: ToTokens> SqlDisplayer<'a, 'b, C, T> { } // Return string representation with context - pub fn to_string(&self) -> Result { + pub fn to_string(&self) -> Result { let mut s = String::new(); let mut stream = WriteTokenStream::new(&mut s); self.start_node.to_tokens(&mut stream, self.ctx)?; @@ -174,7 +181,7 @@ pub trait ToTokens { } // Return string representation with blank context - fn format(&self) -> Result + fn format(&self) -> Result where Self: Sized, { diff --git a/parser/src/error.rs b/parser/src/error.rs index 23e0f4b4b..27fe46956 100644 --- a/parser/src/error.rs +++ b/parser/src/error.rs @@ -52,7 +52,4 @@ pub enum Error { // Custom error message #[error("{0}")] Custom(String), - // formatting error - #[error("{0}")] - FormatError(#[from] std::fmt::Error), } From 4ddfdb2a62e7c69470a7b37a7b7e5f319f2889ed Mon Sep 17 00:00:00 2001 From: TcMits Date: Wed, 27 Aug 2025 14:58:35 +0700 Subject: [PATCH 6/8] finish --- core/incremental/view.rs | 9 +- core/translate/display.rs | 8 +- core/translate/main_loop.rs | 8 +- core/translate/optimizer/mod.rs | 9 +- core/translate/schema.rs | 10 +- core/translate/view.rs | 10 +- core/util.rs | 2 +- core/vdbe/execute.rs | 13 +-- parser/src/ast.rs | 8 -- parser/src/ast/fmt.rs | 137 ++++++++++++++---------- parser/src/parser.rs | 4 +- simulator/model/mod.rs | 6 +- sql_generation/model/query/mod.rs | 18 ---- sql_generation/model/query/predicate.rs | 7 +- sql_generation/model/query/select.rs | 13 +-- 15 files changed, 117 insertions(+), 145 deletions(-) diff --git a/core/incremental/view.rs b/core/incremental/view.rs index 4f4d4c6e6..c40c8ef40 100644 --- a/core/incremental/view.rs +++ b/core/incremental/view.rs @@ -124,14 +124,7 @@ impl IncrementalView { Parser::new(sql.as_bytes()).next_cmd() { // Compare the SELECT statements as SQL strings - use turso_parser::ast::fmt::ToTokens; - - // Format both SELECT statements and compare - if let (Ok(current_sql), Ok(provided_sql)) = - (self.select_stmt.format(), select.format()) - { - return current_sql == provided_sql; - } + return self.select_stmt == select; } false } diff --git a/core/translate/display.rs b/core/translate/display.rs index 1bbb976f5..f183bc3e8 100644 --- a/core/translate/display.rs +++ b/core/translate/display.rs @@ -3,7 +3,7 @@ use std::fmt::{Display, Formatter}; use turso_parser::{ ast::{ self, - fmt::{ToSqlContext, ToTokens, TokenStream}, + fmt::{BlankContext, ToSqlContext, ToTokens, TokenStream}, SortOrder, TableInternalId, }, token::TokenType, @@ -323,6 +323,12 @@ impl ToTokens for Plan { } } +impl Display for JoinedTable { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + self.displayer(&BlankContext).fmt(f) + } +} + impl ToTokens for JoinedTable { fn to_tokens( &self, diff --git a/core/translate/main_loop.rs b/core/translate/main_loop.rs index f190f3424..c326c97c0 100644 --- a/core/translate/main_loop.rs +++ b/core/translate/main_loop.rs @@ -83,8 +83,7 @@ pub fn init_distinct(program: &mut ProgramBuilder, plan: &SelectPlan) -> Distinc name: col .expr .displayer(&PlanContext(&[&plan.table_references])) - .to_string() - .unwrap(), + .to_string(), order: SortOrder::Asc, pos_in_table: i, collation: None, // FIXME: this should be determined based on the result column expression! @@ -159,10 +158,7 @@ pub fn init_loop( ephemeral: true, root_page: 0, columns: vec![IndexColumn { - name: agg.args[0] - .displayer(&PlanContext(&[tables])) - .to_string() - .unwrap(), + name: agg.args[0].displayer(&PlanContext(&[tables])).to_string(), order: SortOrder::Asc, pos_in_table: 0, collation: None, // FIXME: this should be inferred from the expression diff --git a/core/translate/optimizer/mod.rs b/core/translate/optimizer/mod.rs index 7fb16b81b..49b88c402 100644 --- a/core/translate/optimizer/mod.rs +++ b/core/translate/optimizer/mod.rs @@ -8,7 +8,7 @@ use join::{compute_best_join_order, BestJoinOrderResult}; use lift_common_subexpressions::lift_common_subexpressions_from_binary_or_terms; use order::{compute_order_target, plan_satisfies_order_target, EliminatesSortBy}; use turso_ext::{ConstraintInfo, ConstraintUsage}; -use turso_parser::ast::{self, fmt::ToTokens as _, Expr, SortOrder}; +use turso_parser::ast::{self, Expr, SortOrder}; use crate::{ parameters::PARAM_PREFIX, @@ -52,12 +52,7 @@ pub fn optimize_plan(plan: &mut Plan, schema: &Schema) -> Result<()> { } } // When debug tracing is enabled, print the optimized plan as a SQL string for debugging - tracing::debug!( - plan_sql = plan - .displayer(&crate::translate::display::PlanContext(&[])) - .to_string() - .unwrap() - ); + tracing::debug!(plan_sql = plan.to_string()); Ok(()) } diff --git a/core/translate/schema.rs b/core/translate/schema.rs index b40e19216..83002dfba 100644 --- a/core/translate/schema.rs +++ b/core/translate/schema.rs @@ -28,7 +28,6 @@ use crate::SymbolTable; use crate::{bail_parse_error, Result}; use turso_ext::VTabKind; -use turso_parser::ast::fmt::ToTokens; pub fn translate_create_table( tbl_name: ast::QualifiedName, @@ -497,14 +496,7 @@ enum PrimaryKeyDefinitionType<'a> { fn create_table_body_to_str(tbl_name: &ast::QualifiedName, body: &ast::CreateTableBody) -> String { let mut sql = String::new(); - sql.push_str( - format!( - "CREATE TABLE {} {}", - tbl_name.name.as_str(), - body.format().unwrap() - ) - .as_str(), - ); + sql.push_str(format!("CREATE TABLE {} {}", tbl_name.name.as_str(), body).as_str()); match body { ast::CreateTableBody::ColumnsAndConstraints { columns: _, diff --git a/core/translate/view.rs b/core/translate/view.rs index b339e8961..c8dbe47d6 100644 --- a/core/translate/view.rs +++ b/core/translate/view.rs @@ -6,7 +6,7 @@ use crate::vdbe::builder::{CursorType, ProgramBuilder}; use crate::vdbe::insn::{CmpInsFlags, Cookie, Insn}; use crate::{Connection, Result, SymbolTable}; use std::sync::Arc; -use turso_parser::ast::{self, fmt::ToTokens}; +use turso_parser::ast; /// Common logic for creating views (both regular and materialized) fn emit_create_view_program( @@ -112,7 +112,7 @@ fn create_materialized_view_to_str(view_name: &str, select_stmt: &ast::Select) - format!( "CREATE MATERIALIZED VIEW {} AS {}", view_name, - select_stmt.format().unwrap() + select_stmt, ) } @@ -148,11 +148,7 @@ pub fn translate_create_view( } fn create_view_to_str(view_name: &str, select_stmt: &ast::Select) -> String { - format!( - "CREATE VIEW {} AS {}", - view_name, - select_stmt.format().unwrap() - ) + format!("CREATE VIEW {} AS {}", view_name, select_stmt) } pub fn translate_drop_view( diff --git a/core/util.rs b/core/util.rs index 9b7d9e2c8..621552fe1 100644 --- a/core/util.rs +++ b/core/util.rs @@ -1233,7 +1233,7 @@ pub fn extract_view_columns(select_stmt: &ast::Select, schema: &Schema) -> Vec todo!(), @@ -4975,8 +4972,7 @@ pub fn op_function( columns, where_clause, } - .format() - .unwrap(), + .to_string(), ) } ast::Stmt::CreateTable { @@ -5016,8 +5012,7 @@ pub fn op_function( options, }, } - .format() - .unwrap(), + .to_string(), ) } _ => todo!(), diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 144a8be93..db8e6c7c0 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -3,8 +3,6 @@ pub mod fmt; use strum_macros::{EnumIter, EnumString}; -use crate::ast::fmt::ToTokens; - /// `?` or `$` Prepared statement arg placeholder(s) #[derive(Default)] pub struct ParameterInfo { @@ -1146,12 +1144,6 @@ pub enum SortOrder { Desc, } -impl core::fmt::Display for SortOrder { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.to_fmt(f) - } -} - /// `NULLS FIRST` or `NULLS LAST` #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] diff --git a/parser/src/ast/fmt.rs b/parser/src/ast/fmt.rs index 9499ac07a..ee2ddea89 100644 --- a/parser/src/ast/fmt.rs +++ b/parser/src/ast/fmt.rs @@ -144,27 +144,18 @@ impl<'a, 'b, C: ToSqlContext, T: ToTokens> SqlDisplayer<'a, 'b, C, T> { pub fn new(ctx: &'a C, start_node: &'b T) -> Self { Self { ctx, start_node } } - - // Return string representation with context - pub fn to_string(&self) -> Result { - let mut s = String::new(); - let mut stream = WriteTokenStream::new(&mut s); - self.start_node.to_tokens(&mut stream, self.ctx)?; - Ok(s) - } } impl<'a, 'b, C: ToSqlContext, T: ToTokens> Display for SqlDisplayer<'a, 'b, C, T> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let mut stream = WriteTokenStream::new(f); - self.start_node - .to_tokens(&mut stream, self.ctx) - .map_err(|_| fmt::Error) + self.start_node.to_tokens(&mut stream, self.ctx) } } /// Generate token(s) from AST node -pub trait ToTokens { +/// Also implements Display to make sure devs won't forget Display +pub trait ToTokens: Display { /// Send token(s) to the specified stream with context fn to_tokens( &self, @@ -179,14 +170,16 @@ pub trait ToTokens { { SqlDisplayer::new(ctx, self) } +} - // Return string representation with blank context - fn format(&self) -> Result - where - Self: Sized, - { - self.displayer(&BlankContext).to_string() - } +macro_rules! impl_display_for_to_tokens { + ($struct:ty) => { + impl Display for $struct { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + self.displayer(&BlankContext).fmt(f) + } + } + }; } impl ToTokens for &T { @@ -219,6 +212,7 @@ impl ToTokens for String { } } +impl_display_for_to_tokens!(Cmd); impl ToTokens for Cmd { fn to_tokens( &self, @@ -244,12 +238,7 @@ impl ToTokens for Cmd { } } -impl Display for Cmd { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - self.displayer(&BlankContext).fmt(f) - } -} - +impl_display_for_to_tokens!(Stmt); impl ToTokens for Stmt { fn to_tokens( &self, @@ -689,6 +678,7 @@ impl ToTokens for Stmt { } } +impl_display_for_to_tokens!(Expr); impl ToTokens for Expr { fn to_tokens( &self, @@ -804,15 +794,10 @@ impl ToTokens for Expr { } Self::Id(id) => id.to_tokens(s, context), Self::Column { table, column, .. } => { - s.append(TK_ID, context.get_table_name(*table))?; + let (tbl_name, col_name) = context.get_table_and_column_names(*table, *column); + s.append(TK_ID, Some(tbl_name.as_ref()))?; s.append(TK_DOT, None)?; - s.append( - TK_ID, - context - .get_flat_column_name(*table, *column) - .as_ref() - .map(|s| s.as_ref()), - ) + s.append(TK_ID, Some(col_name.as_ref())) } Self::InList { lhs, not, rhs } => { lhs.to_tokens(s, context)?; @@ -925,12 +910,7 @@ impl ToTokens for Expr { } } -impl Display for Expr { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - self.displayer(&BlankContext).fmt(f) - } -} - +impl_display_for_to_tokens!(Literal); impl ToTokens for Literal { fn to_tokens( &self, @@ -950,6 +930,7 @@ impl ToTokens for Literal { } } +impl_display_for_to_tokens!(LikeOperator); impl ToTokens for LikeOperator { fn to_tokens( &self, @@ -968,6 +949,7 @@ impl ToTokens for LikeOperator { } } +impl_display_for_to_tokens!(Operator); impl ToTokens for Operator { fn to_tokens( &self, @@ -1005,6 +987,7 @@ impl ToTokens for Operator { } } +impl_display_for_to_tokens!(UnaryOperator); impl ToTokens for UnaryOperator { fn to_tokens( &self, @@ -1023,6 +1006,7 @@ impl ToTokens for UnaryOperator { } } +impl_display_for_to_tokens!(Select); impl ToTokens for Select { fn to_tokens( &self, @@ -1045,6 +1029,7 @@ impl ToTokens for Select { } } +impl_display_for_to_tokens!(SelectBody); impl ToTokens for SelectBody { fn to_tokens( &self, @@ -1059,6 +1044,7 @@ impl ToTokens for SelectBody { } } +impl_display_for_to_tokens!(CompoundSelect); impl ToTokens for CompoundSelect { fn to_tokens( &self, @@ -1070,6 +1056,7 @@ impl ToTokens for CompoundSelect { } } +impl_display_for_to_tokens!(CompoundOperator); impl ToTokens for CompoundOperator { fn to_tokens( &self, @@ -1088,12 +1075,7 @@ impl ToTokens for CompoundOperator { } } -impl Display for CompoundOperator { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - self.displayer(&BlankContext).fmt(f) - } -} - +impl_display_for_to_tokens!(OneSelect); impl ToTokens for OneSelect { fn to_tokens( &self, @@ -1148,6 +1130,7 @@ impl ToTokens for OneSelect { } } +impl_display_for_to_tokens!(FromClause); impl ToTokens for FromClause { fn to_tokens( &self, @@ -1163,6 +1146,7 @@ impl ToTokens for FromClause { } } +impl_display_for_to_tokens!(Distinctness); impl ToTokens for Distinctness { fn to_tokens( &self, @@ -1179,6 +1163,7 @@ impl ToTokens for Distinctness { } } +impl_display_for_to_tokens!(ResultColumn); impl ToTokens for ResultColumn { fn to_tokens( &self, @@ -1203,6 +1188,7 @@ impl ToTokens for ResultColumn { } } +impl_display_for_to_tokens!(As); impl ToTokens for As { fn to_tokens( &self, @@ -1219,6 +1205,7 @@ impl ToTokens for As { } } +impl_display_for_to_tokens!(JoinedSelectTable); impl ToTokens for JoinedSelectTable { fn to_tokens( &self, @@ -1234,6 +1221,7 @@ impl ToTokens for JoinedSelectTable { } } +impl_display_for_to_tokens!(SelectTable); impl ToTokens for SelectTable { fn to_tokens( &self, @@ -1283,6 +1271,7 @@ impl ToTokens for SelectTable { } } +impl_display_for_to_tokens!(JoinOperator); impl ToTokens for JoinOperator { fn to_tokens( &self, @@ -1301,6 +1290,7 @@ impl ToTokens for JoinOperator { } } +impl_display_for_to_tokens!(JoinType); impl ToTokens for JoinType { fn to_tokens( &self, @@ -1333,6 +1323,7 @@ impl ToTokens for JoinType { } } +impl_display_for_to_tokens!(JoinConstraint); impl ToTokens for JoinConstraint { fn to_tokens( &self, @@ -1354,6 +1345,7 @@ impl ToTokens for JoinConstraint { } } +impl_display_for_to_tokens!(GroupBy); impl ToTokens for GroupBy { fn to_tokens( &self, @@ -1371,6 +1363,7 @@ impl ToTokens for GroupBy { } } +impl_display_for_to_tokens!(Name); impl ToTokens for Name { fn to_tokens( &self, @@ -1381,12 +1374,7 @@ impl ToTokens for Name { } } -impl Display for Name { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - self.displayer(&BlankContext).fmt(f) - } -} - +impl_display_for_to_tokens!(QualifiedName); impl ToTokens for QualifiedName { fn to_tokens( &self, @@ -1406,12 +1394,7 @@ impl ToTokens for QualifiedName { } } -impl Display for QualifiedName { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.displayer(&BlankContext).fmt(f) - } -} - +impl_display_for_to_tokens!(AlterTableBody); impl ToTokens for AlterTableBody { fn to_tokens( &self, @@ -1445,6 +1428,7 @@ impl ToTokens for AlterTableBody { } } +impl_display_for_to_tokens!(CreateTableBody); impl ToTokens for CreateTableBody { fn to_tokens( &self, @@ -1481,6 +1465,7 @@ impl ToTokens for CreateTableBody { } } +impl_display_for_to_tokens!(ColumnDefinition); impl ToTokens for ColumnDefinition { fn to_tokens( &self, @@ -1498,6 +1483,7 @@ impl ToTokens for ColumnDefinition { } } +impl_display_for_to_tokens!(NamedColumnConstraint); impl ToTokens for NamedColumnConstraint { fn to_tokens( &self, @@ -1512,6 +1498,7 @@ impl ToTokens for NamedColumnConstraint { } } +impl_display_for_to_tokens!(ColumnConstraint); impl ToTokens for ColumnConstraint { fn to_tokens( &self, @@ -1602,6 +1589,7 @@ impl ToTokens for ColumnConstraint { } } +impl_display_for_to_tokens!(NamedTableConstraint); impl ToTokens for NamedTableConstraint { fn to_tokens( &self, @@ -1616,6 +1604,7 @@ impl ToTokens for NamedTableConstraint { } } +impl_display_for_to_tokens!(TableConstraint); impl ToTokens for TableConstraint { fn to_tokens( &self, @@ -1685,6 +1674,7 @@ impl ToTokens for TableConstraint { } } +impl_display_for_to_tokens!(SortOrder); impl ToTokens for SortOrder { fn to_tokens( &self, @@ -1701,6 +1691,7 @@ impl ToTokens for SortOrder { } } +impl_display_for_to_tokens!(NullsOrder); impl ToTokens for NullsOrder { fn to_tokens( &self, @@ -1718,6 +1709,7 @@ impl ToTokens for NullsOrder { } } +impl_display_for_to_tokens!(ForeignKeyClause); impl ToTokens for ForeignKeyClause { fn to_tokens( &self, @@ -1737,6 +1729,7 @@ impl ToTokens for ForeignKeyClause { } } +impl_display_for_to_tokens!(RefArg); impl ToTokens for RefArg { fn to_tokens( &self, @@ -1767,6 +1760,7 @@ impl ToTokens for RefArg { } } +impl_display_for_to_tokens!(RefAct); impl ToTokens for RefAct { fn to_tokens( &self, @@ -1792,6 +1786,7 @@ impl ToTokens for RefAct { } } +impl_display_for_to_tokens!(DeferSubclause); impl ToTokens for DeferSubclause { fn to_tokens( &self, @@ -1809,6 +1804,7 @@ impl ToTokens for DeferSubclause { } } +impl_display_for_to_tokens!(InitDeferredPred); impl ToTokens for InitDeferredPred { fn to_tokens( &self, @@ -1826,6 +1822,7 @@ impl ToTokens for InitDeferredPred { } } +impl_display_for_to_tokens!(IndexedColumn); impl ToTokens for IndexedColumn { fn to_tokens( &self, @@ -1844,6 +1841,7 @@ impl ToTokens for IndexedColumn { } } +impl_display_for_to_tokens!(Indexed); impl ToTokens for Indexed { fn to_tokens( &self, @@ -1864,6 +1862,7 @@ impl ToTokens for Indexed { } } +impl_display_for_to_tokens!(SortedColumn); impl ToTokens for SortedColumn { fn to_tokens( &self, @@ -1881,6 +1880,7 @@ impl ToTokens for SortedColumn { } } +impl_display_for_to_tokens!(Limit); impl ToTokens for Limit { fn to_tokens( &self, @@ -1897,6 +1897,7 @@ impl ToTokens for Limit { } } +impl_display_for_to_tokens!(InsertBody); impl ToTokens for InsertBody { fn to_tokens( &self, @@ -1919,6 +1920,7 @@ impl ToTokens for InsertBody { } } +impl_display_for_to_tokens!(Set); impl ToTokens for Set { fn to_tokens( &self, @@ -1937,6 +1939,7 @@ impl ToTokens for Set { } } +impl_display_for_to_tokens!(PragmaBody); impl ToTokens for PragmaBody { fn to_tokens( &self, @@ -1957,6 +1960,7 @@ impl ToTokens for PragmaBody { } } +impl_display_for_to_tokens!(TriggerTime); impl ToTokens for TriggerTime { fn to_tokens( &self, @@ -1974,6 +1978,7 @@ impl ToTokens for TriggerTime { } } +impl_display_for_to_tokens!(TriggerEvent); impl ToTokens for TriggerEvent { fn to_tokens( &self, @@ -1993,6 +1998,7 @@ impl ToTokens for TriggerEvent { } } +impl_display_for_to_tokens!(TriggerCmd); impl ToTokens for TriggerCmd { fn to_tokens( &self, @@ -2077,6 +2083,7 @@ impl ToTokens for TriggerCmd { } } +impl_display_for_to_tokens!(ResolveType); impl ToTokens for ResolveType { fn to_tokens( &self, @@ -2096,6 +2103,7 @@ impl ToTokens for ResolveType { } } +impl_display_for_to_tokens!(With); impl ToTokens for With { fn to_tokens( &self, @@ -2110,6 +2118,7 @@ impl ToTokens for With { } } +impl_display_for_to_tokens!(CommonTableExpr); impl ToTokens for CommonTableExpr { fn to_tokens( &self, @@ -2139,6 +2148,7 @@ impl ToTokens for CommonTableExpr { } } +impl_display_for_to_tokens!(Type); impl ToTokens for Type { fn to_tokens( &self, @@ -2157,6 +2167,7 @@ impl ToTokens for Type { } } +impl_display_for_to_tokens!(TypeSize); impl ToTokens for TypeSize { fn to_tokens( &self, @@ -2174,6 +2185,7 @@ impl ToTokens for TypeSize { } } +impl_display_for_to_tokens!(TransactionType); impl ToTokens for TransactionType { fn to_tokens( &self, @@ -2191,6 +2203,7 @@ impl ToTokens for TransactionType { } } +impl_display_for_to_tokens!(Upsert); impl ToTokens for Upsert { fn to_tokens( &self, @@ -2210,6 +2223,7 @@ impl ToTokens for Upsert { } } +impl_display_for_to_tokens!(UpsertIndex); impl ToTokens for UpsertIndex { fn to_tokens( &self, @@ -2227,6 +2241,7 @@ impl ToTokens for UpsertIndex { } } +impl_display_for_to_tokens!(UpsertDo); impl ToTokens for UpsertDo { fn to_tokens( &self, @@ -2253,6 +2268,7 @@ impl ToTokens for UpsertDo { } } +impl_display_for_to_tokens!(FunctionTail); impl ToTokens for FunctionTail { fn to_tokens( &self, @@ -2274,6 +2290,7 @@ impl ToTokens for FunctionTail { } } +impl_display_for_to_tokens!(Over); impl ToTokens for Over { fn to_tokens( &self, @@ -2287,6 +2304,7 @@ impl ToTokens for Over { } } +impl_display_for_to_tokens!(WindowDef); impl ToTokens for WindowDef { fn to_tokens( &self, @@ -2299,6 +2317,7 @@ impl ToTokens for WindowDef { } } +impl_display_for_to_tokens!(Window); impl ToTokens for Window { fn to_tokens( &self, @@ -2326,6 +2345,7 @@ impl ToTokens for Window { } } +impl_display_for_to_tokens!(FrameClause); impl ToTokens for FrameClause { fn to_tokens( &self, @@ -2349,6 +2369,7 @@ impl ToTokens for FrameClause { } } +impl_display_for_to_tokens!(FrameMode); impl ToTokens for FrameMode { fn to_tokens( &self, @@ -2366,6 +2387,7 @@ impl ToTokens for FrameMode { } } +impl_display_for_to_tokens!(FrameBound); impl ToTokens for FrameBound { fn to_tokens( &self, @@ -2397,6 +2419,7 @@ impl ToTokens for FrameBound { } } +impl_display_for_to_tokens!(FrameExclude); impl ToTokens for FrameExclude { fn to_tokens( &self, diff --git a/parser/src/parser.rs b/parser/src/parser.rs index 6c5253b00..321d7d40c 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -11411,11 +11411,9 @@ mod tests { assert_eq!(results, expected, "Input: {input_str:?}"); - use crate::ast::fmt::{BlankContext, ToTokens}; // to_string tests for (i, r) in results.iter().enumerate() { - let rstring = r.displayer(&BlankContext).to_string().unwrap(); - + let rstring = r.to_string(); // put new string into parser again let result = Parser::new(rstring.as_bytes()).next().unwrap().unwrap(); let expected = &expected[i]; diff --git a/simulator/model/mod.rs b/simulator/model/mod.rs index ce249baf5..d854da4c2 100644 --- a/simulator/model/mod.rs +++ b/simulator/model/mod.rs @@ -8,11 +8,11 @@ use sql_generation::model::{ select::{CompoundOperator, FromClause, ResultColumn, SelectInner}, transaction::{Begin, Commit, Rollback}, update::Update, - Create, CreateIndex, Delete, Drop, EmptyContext, Insert, Select, + Create, CreateIndex, Delete, Drop, Insert, Select, }, table::{JoinTable, JoinType, SimValue, Table, TableContext}, }; -use turso_parser::ast::{fmt::ToTokens, Distinctness}; +use turso_parser::ast::Distinctness; use crate::{generation::Shadow, runner::env::SimulatorTables}; @@ -306,7 +306,7 @@ impl Shadow for SelectInner { } else { return Err(anyhow::anyhow!( "Failed to evaluate expression in free select ({})", - expr.0.format_with_context(&EmptyContext {}).unwrap() + expr.0 )); } } diff --git a/sql_generation/model/query/mod.rs b/sql_generation/model/query/mod.rs index 5bf0cecde..11d117a53 100644 --- a/sql_generation/model/query/mod.rs +++ b/sql_generation/model/query/mod.rs @@ -4,7 +4,6 @@ pub use delete::Delete; pub use drop::Drop; pub use insert::Insert; pub use select::Select; -use turso_parser::ast::fmt::ToSqlContext; pub mod create; pub mod create_index; @@ -15,20 +14,3 @@ pub mod predicate; pub mod select; pub mod transaction; pub mod update; - -/// Used to print sql strings that already have all the context it needs -pub struct EmptyContext; - -impl ToSqlContext for EmptyContext { - fn get_column_name( - &self, - _table_id: turso_parser::ast::TableInternalId, - _col_idx: usize, - ) -> String { - unreachable!() - } - - fn get_table_name(&self, _id: turso_parser::ast::TableInternalId) -> &str { - unreachable!() - } -} diff --git a/sql_generation/model/query/predicate.rs b/sql_generation/model/query/predicate.rs index 29f0b966c..50a72fee4 100644 --- a/sql_generation/model/query/predicate.rs +++ b/sql_generation/model/query/predicate.rs @@ -1,7 +1,10 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; -use turso_parser::ast::{self, fmt::ToTokens}; +use turso_parser::ast::{ + self, + fmt::{BlankContext, ToTokens}, +}; use crate::model::table::{SimValue, Table, TableContext}; @@ -142,6 +145,6 @@ pub fn expr_to_value( impl Display for Predicate { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.0.to_fmt(f) + self.0.displayer(&BlankContext).fmt(f) } } diff --git a/sql_generation/model/query/select.rs b/sql_generation/model/query/select.rs index 6c34888ff..ea4a375db 100644 --- a/sql_generation/model/query/select.rs +++ b/sql_generation/model/query/select.rs @@ -3,13 +3,14 @@ use std::{collections::HashSet, fmt::Display}; pub use ast::Distinctness; use itertools::Itertools; use serde::{Deserialize, Serialize}; -use turso_parser::ast::{self, fmt::ToTokens, SortOrder}; - -use crate::model::{ - query::EmptyContext, - table::{JoinTable, JoinType, JoinedTable, Table}, +use turso_parser::ast::{ + self, + fmt::{BlankContext, ToTokens}, + SortOrder, }; +use crate::model::table::{JoinTable, JoinType, JoinedTable, Table}; + use super::predicate::Predicate; /// `SELECT` or `RETURNING` result column @@ -366,7 +367,7 @@ impl Select { impl Display for Select { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.to_sql_ast().to_fmt_with_context(f, &EmptyContext {}) + self.to_sql_ast().displayer(&BlankContext).fmt(f) } } From bfff90b70ea48fcb29365ffa0207295b50d89569 Mon Sep 17 00:00:00 2001 From: TcMits Date: Wed, 27 Aug 2025 15:02:58 +0700 Subject: [PATCH 7/8] unrelated changes --- parser/src/parser.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/parser/src/parser.rs b/parser/src/parser.rs index 321d7d40c..a6afbe443 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -327,7 +327,7 @@ impl<'a> Parser<'a> { */ match tok.token_type.unwrap() { TK_WINDOW => { - let can_be_window = self.try_parse(|p| -> Result { + let can_be_window = self.try_parse(|p| { match p.consume_lexer_without_whitespaces_or_comments() { None => return Ok(false), Some(tok) => match get_token(tok?.token_type.unwrap()) { @@ -353,7 +353,7 @@ impl<'a> Parser<'a> { let prev_tt = self.current_token.token_type.unwrap_or(TK_EOF); let can_be_over = { if prev_tt == TK_RP { - self.try_parse(|p| -> Result { + self.try_parse(|p| { match p.consume_lexer_without_whitespaces_or_comments() { None => Ok(false), Some(tok) => match get_token(tok?.token_type.unwrap()) { @@ -375,7 +375,7 @@ impl<'a> Parser<'a> { let prev_tt = self.current_token.token_type.unwrap_or(TK_EOF); let can_be_filter = { if prev_tt == TK_RP { - self.try_parse(|p| -> Result { + self.try_parse(|p| { match p.consume_lexer_without_whitespaces_or_comments() { None => Ok(false), Some(tok) => match tok?.token_type.unwrap() { @@ -394,7 +394,7 @@ impl<'a> Parser<'a> { } } TK_UNION => { - let can_be_union = self.try_parse(|p| -> Result { + let can_be_union = self.try_parse(|p| { match p.consume_lexer_without_whitespaces_or_comments() { None => Ok(false), Some(tok) => match tok?.token_type.unwrap() { @@ -409,7 +409,7 @@ impl<'a> Parser<'a> { } } TK_EXCEPT | TK_INTERSECT => { - let can_be_except = self.try_parse(|p| -> Result { + let can_be_except = self.try_parse(|p| { match p.consume_lexer_without_whitespaces_or_comments() { None => Ok(false), Some(tok) => match tok?.token_type.unwrap() { @@ -432,7 +432,7 @@ impl<'a> Parser<'a> { } } TK_GENERATED => { - let can_be_generated = self.try_parse(|p| -> Result { + let can_be_generated = self.try_parse(|p| { match p.consume_lexer_without_whitespaces_or_comments() { None => return Ok(false), Some(tok) => match tok?.token_type.unwrap() { @@ -457,7 +457,7 @@ impl<'a> Parser<'a> { TK_WITHOUT => { let prev_tt = self.current_token.token_type.unwrap_or(TK_EOF); let can_be_without = match prev_tt { - TK_RP | TK_COMMA => self.try_parse(|p| -> Result { + TK_RP | TK_COMMA => self.try_parse(|p| { match p.consume_lexer_without_whitespaces_or_comments() { None => Ok(false), Some(tok) => match get_token(tok?.token_type.unwrap()) { From 1b048b262809d9ffe42ee1fe5b2820eb1c389e50 Mon Sep 17 00:00:00 2001 From: TcMits Date: Wed, 27 Aug 2025 15:08:32 +0700 Subject: [PATCH 8/8] clippy+fmt --- core/translate/view.rs | 8 ++------ parser/src/ast/fmt.rs | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/core/translate/view.rs b/core/translate/view.rs index c8dbe47d6..fcb12df01 100644 --- a/core/translate/view.rs +++ b/core/translate/view.rs @@ -109,11 +109,7 @@ pub fn translate_create_materialized_view( } fn create_materialized_view_to_str(view_name: &str, select_stmt: &ast::Select) -> String { - format!( - "CREATE MATERIALIZED VIEW {} AS {}", - view_name, - select_stmt, - ) + format!("CREATE MATERIALIZED VIEW {view_name} AS {select_stmt}") } pub fn translate_create_view( @@ -148,7 +144,7 @@ pub fn translate_create_view( } fn create_view_to_str(view_name: &str, select_stmt: &ast::Select) -> String { - format!("CREATE VIEW {} AS {}", view_name, select_stmt) + format!("CREATE VIEW {view_name} AS {select_stmt}") } pub fn translate_drop_view( diff --git a/parser/src/ast/fmt.rs b/parser/src/ast/fmt.rs index ee2ddea89..0f7ab3d9b 100644 --- a/parser/src/ast/fmt.rs +++ b/parser/src/ast/fmt.rs @@ -40,9 +40,9 @@ pub trait ToSqlContext { .get_column_name(table_id, col_idx) .map(|opt| { opt.map(|s| s.to_owned()) - .unwrap_or_else(|| format!("c{}", col_idx)) + .unwrap_or_else(|| format!("c{col_idx}")) }) - .unwrap_or_else(|| format!("c{}", col_idx)); + .unwrap_or_else(|| format!("c{col_idx}")); (table_name, column_name) }