From 5aa74410b3ddf9d0edfcae66a5bcd0c9fb100b5d Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 3 Apr 2022 22:24:27 +0800 Subject: [PATCH 1/5] issues-179 Add support for view without backend impl --- src/backend/mod.rs | 4 +- src/backend/mysql/mod.rs | 1 + src/backend/mysql/view.rs | 3 + src/backend/postgres/mod.rs | 1 + src/backend/postgres/view.rs | 3 + src/backend/sqlite/mod.rs | 1 + src/backend/sqlite/view.rs | 5 ++ src/backend/view_builder.rs | 9 +++ src/lib.rs | 2 + src/schema.rs | 5 +- src/view/create.rs | 121 +++++++++++++++++++++++++++++++++++ src/view/drop.rs | 87 +++++++++++++++++++++++++ src/view/mod.rs | 73 +++++++++++++++++++++ src/view/rename.rs | 61 ++++++++++++++++++ src/view/shim.rs | 5 ++ 15 files changed, 379 insertions(+), 2 deletions(-) create mode 100644 src/backend/mysql/view.rs create mode 100644 src/backend/postgres/view.rs create mode 100644 src/backend/sqlite/view.rs create mode 100644 src/backend/view_builder.rs create mode 100644 src/view/create.rs create mode 100644 src/view/drop.rs create mode 100644 src/view/mod.rs create mode 100644 src/view/rename.rs create mode 100644 src/view/shim.rs diff --git a/src/backend/mod.rs b/src/backend/mod.rs index ebbd27bd2..3c094e64c 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -24,16 +24,18 @@ mod index_builder; mod query_builder; mod table_builder; mod table_ref_builder; +mod view_builder; pub use self::foreign_key_builder::*; pub use self::index_builder::*; pub use self::query_builder::*; pub use self::table_builder::*; pub use self::table_ref_builder::*; +pub use self::view_builder::*; pub trait GenericBuilder: QueryBuilder + SchemaBuilder {} -pub trait SchemaBuilder: TableBuilder + IndexBuilder + ForeignKeyBuilder {} +pub trait SchemaBuilder: TableBuilder + IndexBuilder + ForeignKeyBuilder + ViewBuilder {} pub trait QuotedBuilder { /// The type of quote the builder uses. diff --git a/src/backend/mysql/mod.rs b/src/backend/mysql/mod.rs index 4a87ed70b..d4dccbdd7 100644 --- a/src/backend/mysql/mod.rs +++ b/src/backend/mysql/mod.rs @@ -2,6 +2,7 @@ pub(crate) mod foreign_key; pub(crate) mod index; pub(crate) mod query; pub(crate) mod table; +pub(crate) mod view; use super::*; diff --git a/src/backend/mysql/view.rs b/src/backend/mysql/view.rs new file mode 100644 index 000000000..7b157c261 --- /dev/null +++ b/src/backend/mysql/view.rs @@ -0,0 +1,3 @@ +use crate::*; + +impl ViewBuilder for MysqlQueryBuilder {} diff --git a/src/backend/postgres/mod.rs b/src/backend/postgres/mod.rs index aa679b5c9..a5d9bc203 100644 --- a/src/backend/postgres/mod.rs +++ b/src/backend/postgres/mod.rs @@ -3,6 +3,7 @@ pub(crate) mod index; pub(crate) mod query; pub(crate) mod table; pub(crate) mod types; +pub(crate) mod view; use super::*; diff --git a/src/backend/postgres/view.rs b/src/backend/postgres/view.rs new file mode 100644 index 000000000..b3b87b027 --- /dev/null +++ b/src/backend/postgres/view.rs @@ -0,0 +1,3 @@ +use crate::*; + +impl ViewBuilder for PostgresQueryBuilder {} diff --git a/src/backend/sqlite/mod.rs b/src/backend/sqlite/mod.rs index c99e24a3a..0774f56f8 100644 --- a/src/backend/sqlite/mod.rs +++ b/src/backend/sqlite/mod.rs @@ -2,6 +2,7 @@ pub(crate) mod foreign_key; pub(crate) mod index; pub(crate) mod query; pub(crate) mod table; +pub(crate) mod view; use super::*; diff --git a/src/backend/sqlite/view.rs b/src/backend/sqlite/view.rs new file mode 100644 index 000000000..36fd25ab6 --- /dev/null +++ b/src/backend/sqlite/view.rs @@ -0,0 +1,5 @@ +use crate::*; + +impl ViewBuilder for SqliteQueryBuilder { + fn prepare_view_rename_statement(&self, rename: &ViewRenameStatement, sql: &mut SqlWriter) {} +} diff --git a/src/backend/view_builder.rs b/src/backend/view_builder.rs new file mode 100644 index 000000000..d027d976e --- /dev/null +++ b/src/backend/view_builder.rs @@ -0,0 +1,9 @@ +use crate::*; + +pub trait ViewBuilder: QueryBuilder + QuotedBuilder { + fn prepare_view_create_statement(&self, create: &ViewCreateStatement, sql: &mut SqlWriter) {} + + fn prepare_view_drop_statement(&self, drop: &ViewDropStatement, sql: &mut SqlWriter) {} + + fn prepare_view_rename_statement(&self, rename: &ViewRenameStatement, sql: &mut SqlWriter) {} +} diff --git a/src/lib.rs b/src/lib.rs index 6854a3fb8..4cdd67ef3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -832,6 +832,7 @@ pub mod tests_cfg; pub mod token; pub mod types; pub mod value; +pub mod view; pub use backend::*; //pub use extension::*; @@ -849,6 +850,7 @@ pub use schema::*; pub use token::*; pub use types::*; pub use value::*; +pub use view::*; #[cfg(feature = "derive")] pub use sea_query_derive::{Iden, IdenStatic}; diff --git a/src/schema.rs b/src/schema.rs index 7e03c455f..9c04452ec 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -1,12 +1,15 @@ //! Schema definition & alternations statements -use crate::{backend::SchemaBuilder, ForeignKeyStatement, IndexStatement, TableStatement}; +use crate::{ + backend::SchemaBuilder, ForeignKeyStatement, IndexStatement, TableStatement, ViewStatement, +}; #[derive(Debug, Clone)] pub enum SchemaStatement { TableStatement(TableStatement), IndexStatement(IndexStatement), ForeignKeyStatement(ForeignKeyStatement), + ViewStatement(ViewStatement), } pub trait SchemaStatementBuilder { diff --git a/src/view/create.rs b/src/view/create.rs new file mode 100644 index 000000000..9380fdf72 --- /dev/null +++ b/src/view/create.rs @@ -0,0 +1,121 @@ +use crate::{ + backend::SchemaBuilder, prepare::*, query::SelectStatement, types::*, SchemaStatementBuilder, +}; + +/// Create a view +/// +/// # Examples +/// +/// ``` +/// ``` +#[derive(Debug, Clone)] +pub struct ViewCreateStatement { + pub(crate) view: Option, + pub(crate) columns: Vec, + pub(crate) select: Option, + pub(crate) or_replace: bool, + pub(crate) if_not_exists: bool, +} + +impl Default for ViewCreateStatement { + fn default() -> Self { + Self::new() + } +} + +impl ViewCreateStatement { + /// Construct create view statement. + pub fn new() -> Self { + Self { + view: None, + columns: Vec::new(), + select: None, + if_not_exists: false, + or_replace: false, + } + } + + /// Create view if view not exists. + pub fn if_not_exists(&mut self) -> &mut Self { + self.if_not_exists = true; + self + } + + /// Create or replace view. + pub fn or_replace(&mut self) -> &mut Self { + self.or_replace = true; + self + } + + /// Set view name. + pub fn view(&mut self, view: T) -> &mut Self + where + T: IntoTableRef, + { + self.view = Some(view.into_table_ref()); + self + } + + /// Add a new view column. + pub fn column(&mut self, column: C) -> &mut Self + where + C: IntoIden, + { + let column = column.into_iden(); + self.columns.push(column); + self + } + + /// Adds a columns to the view definition. + pub fn columns(&mut self, cols: I) -> &mut Self + where + T: IntoIden, + I: IntoIterator, + { + self.columns + .extend(cols.into_iter().map(|col| col.into_iden())); + self + } + + /// Adds AS select query to the view. + pub fn select(&mut self, select: SelectStatement) -> &mut Self { + self.select = Some(select); + self + } + + pub fn get_view_name(&self) -> Option<&TableRef> { + self.view.as_ref() + } + + pub fn get_columns(&self) -> &Vec { + self.columns.as_ref() + } + + pub fn get_select(&self) -> Option<&SelectStatement> { + self.select.as_ref() + } + + pub fn take(&mut self) -> Self { + Self { + view: self.view.take(), + columns: std::mem::take(&mut self.columns), + select: self.select.take(), + or_replace: self.or_replace, + if_not_exists: self.if_not_exists, + } + } +} + +impl SchemaStatementBuilder for ViewCreateStatement { + fn build(&self, schema_builder: T) -> String { + let mut sql = SqlWriter::new(); + schema_builder.prepare_view_create_statement(self, &mut sql); + sql.result() + } + + fn build_any(&self, schema_builder: &dyn SchemaBuilder) -> String { + let mut sql = SqlWriter::new(); + schema_builder.prepare_view_create_statement(self, &mut sql); + sql.result() + } +} diff --git a/src/view/drop.rs b/src/view/drop.rs new file mode 100644 index 000000000..38f5bc6a3 --- /dev/null +++ b/src/view/drop.rs @@ -0,0 +1,87 @@ +use crate::{backend::SchemaBuilder, prepare::*, types::*, SchemaStatementBuilder}; + +/// Drop a view +/// +/// # Examples +/// +/// ``` +/// ``` +#[derive(Debug, Clone)] +pub struct ViewDropStatement { + pub(crate) views: Vec, + pub(crate) options: Vec, + pub(crate) if_exists: bool, +} + +/// All available view drop options. +#[derive(Debug, Clone)] +pub enum ViewDropOpt { + Restrict, + Cascade, +} + +impl Default for ViewDropStatement { + fn default() -> Self { + Self::new() + } +} + +impl ViewDropStatement { + /// Construct drop view statement. + pub fn new() -> Self { + Self { + views: Vec::new(), + options: Vec::new(), + if_exists: false, + } + } + + /// Set view name. + pub fn view(&mut self, view: T) -> &mut Self + where + T: IntoTableRef, + { + self.views.push(view.into_table_ref()); + self + } + + /// Drop view if exists. + pub fn if_exists(&mut self) -> &mut Self { + self.if_exists = true; + self + } + + /// Drop option restrict. + pub fn restrict(&mut self) -> &mut Self { + self.options.push(ViewDropOpt::Restrict); + self + } + + /// Drop option cacade. + pub fn cascade(&mut self) -> &mut Self { + self.options.push(ViewDropOpt::Cascade); + self + } + + pub fn take(&mut self) -> Self { + Self { + views: std::mem::take(&mut self.views), + options: std::mem::take(&mut self.options), + if_exists: self.if_exists, + } + } +} + +impl SchemaStatementBuilder for ViewDropStatement { + fn build(&self, schema_builder: T) -> String { + let mut sql = SqlWriter::new(); + schema_builder.prepare_view_drop_statement(self, &mut sql); + sql.result() + } + + fn build_any(&self, schema_builder: &dyn SchemaBuilder) -> String { + let mut sql = SqlWriter::new(); + schema_builder.prepare_view_drop_statement(self, &mut sql); + sql.result() + } +} diff --git a/src/view/mod.rs b/src/view/mod.rs new file mode 100644 index 000000000..3e5ac08eb --- /dev/null +++ b/src/view/mod.rs @@ -0,0 +1,73 @@ +//! View definition statements. +//! +//! # Usage +//! +//! - View Create, see [`ViewCreateStatement`] +//! - Table Drop, see [`ViewDropStatement`] +//! - Table Rename, see [`ViewRenameStatement`] + +use crate::SchemaBuilder; + +mod create; +mod drop; +mod rename; +mod shim; + +pub use create::*; +pub use drop::*; +pub use rename::*; + +/// Helper for constructing any view statement +#[derive(Debug)] +pub struct View; + +/// All available types of view statement +#[derive(Debug, Clone)] +pub enum ViewStatement { + Create(ViewCreateStatement), + Rename(ViewRenameStatement), + Drop(ViewDropStatement), +} + +impl View { + pub fn create() -> ViewCreateStatement { + ViewCreateStatement::new() + } + + pub fn rename() -> ViewRenameStatement { + ViewRenameStatement::new() + } + + pub fn drop() -> ViewDropStatement { + ViewDropStatement::new() + } +} + +impl ViewStatement { + /// Build corresponding SQL statement for certain database backend and return SQL string + pub fn build(&self, view_builder: T) -> String { + match self { + Self::Create(stat) => stat.build(view_builder), + Self::Drop(stat) => stat.build(view_builder), + Self::Rename(stat) => stat.build(view_builder), + } + } + + /// Build corresponding SQL statement for certain database backend and return SQL string + pub fn build_any(&self, view_builder: &dyn SchemaBuilder) -> String { + match self { + Self::Create(stat) => stat.build_any(view_builder), + Self::Drop(stat) => stat.build_any(view_builder), + Self::Rename(stat) => stat.build_any(view_builder), + } + } + + /// Build corresponding SQL statement for certain database backend and return SQL string + pub fn to_string(&self, view_builder: T) -> String { + match self { + Self::Create(stat) => stat.to_string(view_builder), + Self::Drop(stat) => stat.to_string(view_builder), + Self::Rename(stat) => stat.to_string(view_builder), + } + } +} diff --git a/src/view/rename.rs b/src/view/rename.rs new file mode 100644 index 000000000..9aa188503 --- /dev/null +++ b/src/view/rename.rs @@ -0,0 +1,61 @@ +use crate::{backend::SchemaBuilder, prepare::*, types::*, SchemaStatementBuilder}; + +/// Rename a view +/// +/// # Examples +/// +/// ``` +/// ``` +#[derive(Debug, Clone)] +pub struct ViewRenameStatement { + pub(crate) from_name: Option, + pub(crate) to_name: Option, +} + +impl Default for ViewRenameStatement { + fn default() -> Self { + Self::new() + } +} + +impl ViewRenameStatement { + /// Construct rename view statement. + pub fn new() -> Self { + Self { + from_name: None, + to_name: None, + } + } + + /// Set old and new view name. + pub fn view(&mut self, from_name: T, to_name: R) -> &mut Self + where + T: Iden, + R: Iden, + { + self.from_name = Some(SeaRc::new(from_name)); + self.to_name = Some(SeaRc::new(to_name)); + self + } + + pub fn take(&mut self) -> Self { + Self { + from_name: self.from_name.take(), + to_name: self.to_name.take(), + } + } +} + +impl SchemaStatementBuilder for ViewRenameStatement { + fn build(&self, view_builder: T) -> String { + let mut sql = SqlWriter::new(); + view_builder.prepare_view_rename_statement(self, &mut sql); + sql.result() + } + + fn build_any(&self, view_builder: &dyn SchemaBuilder) -> String { + let mut sql = SqlWriter::new(); + view_builder.prepare_view_rename_statement(self, &mut sql); + sql.result() + } +} diff --git a/src/view/shim.rs b/src/view/shim.rs new file mode 100644 index 000000000..a09472bb4 --- /dev/null +++ b/src/view/shim.rs @@ -0,0 +1,5 @@ +use crate::impl_schema_statement_builder; + +impl_schema_statement_builder!(view_create_statement_builder, ViewCreateStatement); +impl_schema_statement_builder!(view_drop_statement_builder, ViewDropStatement); +impl_schema_statement_builder!(view_rename_statement_builder, ViewRenameStatement); From 2261d2d2fcf7ec7c743f45b70828f133693f68ae Mon Sep 17 00:00:00 2001 From: Ivan Krivosheev Date: Tue, 5 Apr 2022 23:42:40 +0300 Subject: [PATCH 2/5] issues-179 Add backend generators --- src/backend/mysql/view.rs | 13 ++++- src/backend/postgres/view.rs | 27 ++++++++- src/backend/sqlite/view.rs | 34 +++++++++++- src/backend/view_builder.rs | 105 ++++++++++++++++++++++++++++++++++- src/query/delete.rs | 6 +- src/query/insert.rs | 14 +++-- src/query/select.rs | 6 +- src/query/traits.rs | 2 + src/query/update.rs | 6 +- src/query/with.rs | 9 ++- src/view/create.rs | 46 ++++++++++++--- 11 files changed, 240 insertions(+), 28 deletions(-) diff --git a/src/backend/mysql/view.rs b/src/backend/mysql/view.rs index 7b157c261..5c73ceb7f 100644 --- a/src/backend/mysql/view.rs +++ b/src/backend/mysql/view.rs @@ -1,3 +1,14 @@ use crate::*; -impl ViewBuilder for MysqlQueryBuilder {} +impl ViewBuilder for MysqlQueryBuilder { + fn prepare_view_rename_statement(&self, rename: &ViewRenameStatement, sql: &mut SqlWriter) { + write!(sql, "RENAME TABLE ").unwrap(); + if let Some(from_name) = &rename.from_name { + from_name.prepare(sql, self.quote()); + } + write!(sql, " TO ").unwrap(); + if let Some(to_name) = &rename.to_name { + to_name.prepare(sql, self.quote()); + } + } +} diff --git a/src/backend/postgres/view.rs b/src/backend/postgres/view.rs index b3b87b027..8ac2fc265 100644 --- a/src/backend/postgres/view.rs +++ b/src/backend/postgres/view.rs @@ -1,3 +1,28 @@ use crate::*; -impl ViewBuilder for PostgresQueryBuilder {} +impl ViewBuilder for PostgresQueryBuilder { + fn prepare_view_create_befor_view(&self, create: &ViewCreateStatement, sql: &mut SqlWriter) { + if create.or_replace { + write!(sql, " OR REPLACE").unwrap(); + } + + if create.temporary { + write!(sql, " TEMPORARY").unwrap(); + } + + if create.recursive { + write!(sql, " RECURSIVE").unwrap(); + } + } + + fn prepare_view_rename_statement(&self, rename: &ViewRenameStatement, sql: &mut SqlWriter) { + write!(sql, "ALTER VIEW ").unwrap(); + if let Some(from_name) = &rename.from_name { + from_name.prepare(sql, self.quote()); + } + write!(sql, " TO ").unwrap(); + if let Some(to_name) = &rename.to_name { + to_name.prepare(sql, self.quote()); + } + } +} diff --git a/src/backend/sqlite/view.rs b/src/backend/sqlite/view.rs index 36fd25ab6..fd5b60e45 100644 --- a/src/backend/sqlite/view.rs +++ b/src/backend/sqlite/view.rs @@ -1,5 +1,37 @@ use crate::*; impl ViewBuilder for SqliteQueryBuilder { - fn prepare_view_rename_statement(&self, rename: &ViewRenameStatement, sql: &mut SqlWriter) {} + fn prepare_view_create_befor_view(&self, create: &ViewCreateStatement, sql: &mut SqlWriter) { + if create.temporary { + write!(sql, " TEMPORARY").unwrap(); + } + } + + fn prepare_view_create_after_view(&self, create: &ViewCreateStatement, sql: &mut SqlWriter) { + if create.if_not_exists { + write!(sql, " IF NOT EXISTS").unwrap(); + } + } + + fn prepare_view_create_opt_update(&self, _opt: &ViewCreateOpt, _sql: &mut SqlWriter) { + // SQLite does not support view create options + } + + fn prepare_view_rename_statement(&self, _rename: &ViewRenameStatement, _sql: &mut SqlWriter) { + // SQLite does not support rename view + } + + /// Translate [`ViewDropStatement`] into SQL statement. + fn prepare_view_drop_statement(&self, drop: &ViewDropStatement, sql: &mut SqlWriter) { + write!(sql, "DROP VIEW ").unwrap(); + + if drop.if_exists { + write!(sql, "IF EXISTS ").unwrap(); + } + self.prepare_view_ref(&drop.views[0], sql); + } + + fn prepare_view_drop_opt(&self, _drop_opt: &ViewDropOpt, _sql: &mut dyn std::fmt::Write) { + // SQLite does not support view drop options + } } diff --git a/src/backend/view_builder.rs b/src/backend/view_builder.rs index d027d976e..d734f2326 100644 --- a/src/backend/view_builder.rs +++ b/src/backend/view_builder.rs @@ -1,9 +1,108 @@ use crate::*; pub trait ViewBuilder: QueryBuilder + QuotedBuilder { - fn prepare_view_create_statement(&self, create: &ViewCreateStatement, sql: &mut SqlWriter) {} + /// Translate [`ViewCreateStatement`] into SQL statement. + fn prepare_view_create_statement(&self, create: &ViewCreateStatement, sql: &mut SqlWriter) { + write!(sql, "CREATE").unwrap(); + self.prepare_view_create_befor_view(create, sql); - fn prepare_view_drop_statement(&self, drop: &ViewDropStatement, sql: &mut SqlWriter) {} + write!(sql, " VIEW ").unwrap(); + self.prepare_view_create_after_view(create, sql); - fn prepare_view_rename_statement(&self, rename: &ViewRenameStatement, sql: &mut SqlWriter) {} + if let Some(view_ref) = &create.view { + self.prepare_view_ref(view_ref, sql); + } + + if !create.columns.is_empty() { + write!(sql, " ( ").unwrap(); + create.columns.iter().fold(true, |first, column| { + if !first { + write!(sql, ", ").unwrap(); + } + column.prepare(sql, self.quote()); + false + }); + write!(sql, " ) ").unwrap(); + } + + write!(sql, " AS ").unwrap(); + // self.prepare_select_statement(create.query, sql); + if let Some(opt) = &create.opt { + self.prepare_view_create_opt_update(opt, sql); + } + } + + fn prepare_view_create_befor_view(&self, _create: &ViewCreateStatement, _sql: &mut SqlWriter) {} + + fn prepare_view_create_after_view(&self, _create: &ViewCreateStatement, _sql: &mut SqlWriter) {} + + fn prepare_view_create_opt_update(&self, opt: &ViewCreateOpt, sql: &mut SqlWriter) { + write!(sql, " WITH ").unwrap(); + match opt { + ViewCreateOpt::Cascade => write!(sql, "CASCADED").unwrap(), + ViewCreateOpt::Local => write!(sql, "LOCAL").unwrap(), + } + write!(sql, " CHECK OPTION").unwrap(); + } + + fn prepare_view_rename_statement(&self, _rename: &ViewRenameStatement, _sql: &mut SqlWriter); + + /// Translate [`ViewDropStatement`] into SQL statement. + fn prepare_view_drop_statement(&self, drop: &ViewDropStatement, sql: &mut SqlWriter) { + write!(sql, "DROP VIEW ").unwrap(); + + if drop.if_exists { + write!(sql, "IF EXISTS ").unwrap(); + } + + drop.views.iter().fold(true, |first, view| { + if !first { + write!(sql, ", ").unwrap(); + } + self.prepare_view_ref(view, sql); + false + }); + + let mut view_drop_opt = String::new(); + for drop_opt in drop.options.iter() { + write!(&mut view_drop_opt, " ").unwrap(); + self.prepare_view_drop_opt(drop_opt, &mut view_drop_opt); + } + write!(sql, "{}", view_drop_opt.trim_end()).unwrap(); + } + + /// Translate [`ViewDropOpt`] into SQL statement. + fn prepare_view_drop_opt(&self, drop_opt: &ViewDropOpt, sql: &mut dyn std::fmt::Write) { + write!( + sql, + "{}", + match drop_opt { + ViewDropOpt::Restrict => "RESTRICT", + ViewDropOpt::Cascade => "CASCADE", + } + ) + .unwrap(); + } + + /// Translate [`TableRef`] into SQL statement. + fn prepare_view_ref(&self, table_ref: &TableRef, sql: &mut SqlWriter) { + match table_ref { + TableRef::Table(table) => { + table.prepare(sql, self.quote()); + } + TableRef::SchemaTable(schema, table) => { + schema.prepare(sql, self.quote()); + write!(sql, ".").unwrap(); + table.prepare(sql, self.quote()); + } + TableRef::DatabaseSchemaTable(database, schema, table) => { + database.prepare(sql, self.quote()); + write!(sql, ".").unwrap(); + schema.prepare(sql, self.quote()); + write!(sql, ".").unwrap(); + table.prepare(sql, self.quote()); + } + _ => panic!("Not supported"), + } + } } diff --git a/src/query/delete.rs b/src/query/delete.rs index a132f3198..788896efa 100644 --- a/src/query/delete.rs +++ b/src/query/delete.rs @@ -4,8 +4,8 @@ use crate::{ query::{condition::*, OrderedStatement}, types::*, value::*, - QueryStatementBuilder, QueryStatementWriter, ReturningClause, SubQueryStatement, WithClause, - WithQuery, + QueryStatementBuilder, QueryStatementWriter, ReturningClause, SubQueryBuilder, + SubQueryStatement, WithClause, WithQuery, }; /// Delete existing rows from the table @@ -231,7 +231,9 @@ impl QueryStatementBuilder for DeleteStatement { fn build_collect_any_into(&self, query_builder: &dyn QueryBuilder, sql: &mut dyn SqlWriter) { query_builder.prepare_delete_statement(self, sql); } +} +impl SubQueryBuilder for DeleteStatement { fn into_sub_query_statement(self) -> SubQueryStatement { SubQueryStatement::DeleteStatement(self) } diff --git a/src/query/insert.rs b/src/query/insert.rs index aa4cc14d9..afbc7b6ce 100644 --- a/src/query/insert.rs +++ b/src/query/insert.rs @@ -1,7 +1,7 @@ use crate::{ backend::QueryBuilder, error::*, prepare::*, types::*, OnConflict, QueryStatementBuilder, - QueryStatementWriter, ReturningClause, SelectStatement, SimpleExpr, SubQueryStatement, - WithClause, WithQuery, + QueryStatementWriter, ReturningClause, SelectStatement, SimpleExpr, SubQueryBuilder, + SubQueryStatement, WithClause, WithQuery, }; /// Represents a value source that can be used in an insert query. @@ -521,10 +521,6 @@ impl QueryStatementBuilder for InsertStatement { fn build_collect_any_into(&self, query_builder: &dyn QueryBuilder, sql: &mut dyn SqlWriter) { query_builder.prepare_insert_statement(self, sql); } - - fn into_sub_query_statement(self) -> SubQueryStatement { - SubQueryStatement::InsertStatement(self) - } } impl QueryStatementWriter for InsertStatement { @@ -532,3 +528,9 @@ impl QueryStatementWriter for InsertStatement { query_builder.prepare_insert_statement(self, sql); } } + +impl SubQueryBuilder for InsertStatement { + fn into_sub_query_statement(self) -> SubQueryStatement { + SubQueryStatement::InsertStatement(self) + } +} diff --git a/src/query/select.rs b/src/query/select.rs index c848809f5..2f97fc886 100644 --- a/src/query/select.rs +++ b/src/query/select.rs @@ -5,8 +5,8 @@ use crate::{ query::{condition::*, OrderedStatement}, types::*, value::*, - FunctionCall, QueryStatementBuilder, QueryStatementWriter, SubQueryStatement, WindowStatement, - WithClause, WithQuery, + FunctionCall, QueryStatementBuilder, QueryStatementWriter, SubQueryBuilder, SubQueryStatement, + WindowStatement, WithClause, WithQuery, }; /// Select rows from an existing table @@ -2279,7 +2279,9 @@ impl QueryStatementBuilder for SelectStatement { fn build_collect_any_into(&self, query_builder: &dyn QueryBuilder, sql: &mut dyn SqlWriter) { query_builder.prepare_select_statement(self, sql); } +} +impl SubQueryBuilder for SelectStatement { fn into_sub_query_statement(self) -> SubQueryStatement { SubQueryStatement::SelectStatement(self) } diff --git a/src/query/traits.rs b/src/query/traits.rs index 2c172bcf1..196aa6701 100644 --- a/src/query/traits.rs +++ b/src/query/traits.rs @@ -23,7 +23,9 @@ pub trait QueryStatementBuilder: Debug { /// Build corresponding SQL statement into the SqlWriter for certain database backend and collect query parameters fn build_collect_any_into(&self, query_builder: &dyn QueryBuilder, sql: &mut dyn SqlWriter); +} +pub trait SubQueryBuilder: Debug { fn into_sub_query_statement(self) -> SubQueryStatement; } diff --git a/src/query/update.rs b/src/query/update.rs index f4db41771..d3555be0b 100644 --- a/src/query/update.rs +++ b/src/query/update.rs @@ -5,8 +5,8 @@ use crate::{ query::{condition::*, OrderedStatement}, types::*, value::*, - QueryStatementBuilder, QueryStatementWriter, ReturningClause, SubQueryStatement, WithClause, - WithQuery, + QueryStatementBuilder, QueryStatementWriter, ReturningClause, SubQueryBuilder, + SubQueryStatement, WithClause, WithQuery, }; /// Update existing rows in the table @@ -293,7 +293,9 @@ impl QueryStatementBuilder for UpdateStatement { fn build_collect_any_into(&self, query_builder: &dyn QueryBuilder, sql: &mut dyn SqlWriter) { query_builder.prepare_update_statement(self, sql); } +} +impl SubQueryBuilder for UpdateStatement { fn into_sub_query_statement(self) -> SubQueryStatement { SubQueryStatement::UpdateStatement(self) } diff --git a/src/query/with.rs b/src/query/with.rs index dab0c81b6..7650ea340 100644 --- a/src/query/with.rs +++ b/src/query/with.rs @@ -7,6 +7,7 @@ use crate::SelectExpr; use crate::SelectStatement; use crate::SimpleExpr; use crate::SqlWriter; +use crate::SubQueryBuilder; use crate::SubQueryStatement; use crate::TableRef; use crate::{Alias, QueryBuilder}; @@ -109,7 +110,7 @@ impl CommonTableExpression { /// columns. pub fn query(&mut self, query: Q) -> &mut Self where - Q: QueryStatementBuilder, + Q: SubQueryBuilder, { self.query = Some(Box::new(query.into_sub_query_statement())); self @@ -491,7 +492,7 @@ impl WithClause { /// execute the argument query with this WITH clause. pub fn query(self, query: T) -> WithQuery where - T: QueryStatementBuilder + 'static, + T: SubQueryBuilder + 'static, { WithQuery::new().with_clause(self).query(query).to_owned() } @@ -582,7 +583,7 @@ impl WithQuery { /// Set the query that you execute with the [WithClause]. pub fn query(&mut self, query: T) -> &mut Self where - T: QueryStatementBuilder, + T: SubQueryBuilder, { self.query = Some(Box::new(query.into_sub_query_statement())); self @@ -593,7 +594,9 @@ impl QueryStatementBuilder for WithQuery { fn build_collect_any_into(&self, query_builder: &dyn QueryBuilder, sql: &mut dyn SqlWriter) { query_builder.prepare_with_query(self, sql); } +} +impl SubQueryBuilder for WithQuery { fn into_sub_query_statement(self) -> SubQueryStatement { SubQueryStatement::WithStatement(self) } diff --git a/src/view/create.rs b/src/view/create.rs index 9380fdf72..3fda1813b 100644 --- a/src/view/create.rs +++ b/src/view/create.rs @@ -12,9 +12,18 @@ use crate::{ pub struct ViewCreateStatement { pub(crate) view: Option, pub(crate) columns: Vec, - pub(crate) select: Option, + pub(crate) query: SelectStatement, pub(crate) or_replace: bool, pub(crate) if_not_exists: bool, + pub(crate) recursive: bool, + pub(crate) temporary: bool, + pub(crate) opt: Option, +} + +#[derive(Debug, Clone)] +pub enum ViewCreateOpt { + Cascade, + Local, } impl Default for ViewCreateStatement { @@ -29,9 +38,12 @@ impl ViewCreateStatement { Self { view: None, columns: Vec::new(), - select: None, + query: SelectStatement::new(), if_not_exists: false, or_replace: false, + recursive: false, + temporary: false, + opt: None, } } @@ -47,6 +59,18 @@ impl ViewCreateStatement { self } + /// Create recursive view . + pub fn recursive(&mut self) -> &mut Self { + self.recursive = true; + self + } + + /// Create temporary view. + pub fn temporary(&mut self) -> &mut Self { + self.temporary = true; + self + } + /// Set view name. pub fn view(&mut self, view: T) -> &mut Self where @@ -78,8 +102,13 @@ impl ViewCreateStatement { } /// Adds AS select query to the view. - pub fn select(&mut self, select: SelectStatement) -> &mut Self { - self.select = Some(select); + pub fn query(&mut self, select: SelectStatement) -> &mut Self { + self.query = select; + self + } + + pub fn create_opt(&mut self, opt: ViewCreateOpt) -> &mut Self { + self.opt = Some(opt); self } @@ -91,17 +120,20 @@ impl ViewCreateStatement { self.columns.as_ref() } - pub fn get_select(&self) -> Option<&SelectStatement> { - self.select.as_ref() + pub fn get_query(&self) -> &SelectStatement { + &self.query } pub fn take(&mut self) -> Self { Self { view: self.view.take(), columns: std::mem::take(&mut self.columns), - select: self.select.take(), + query: self.query.take(), or_replace: self.or_replace, if_not_exists: self.if_not_exists, + recursive: self.recursive, + temporary: self.temporary, + opt: self.opt.take(), } } } From ccc18fbda913f8d74ef0079920302d8f95f6505d Mon Sep 17 00:00:00 2001 From: Ivan Krivosheev Date: Tue, 5 Apr 2022 23:50:53 +0300 Subject: [PATCH 3/5] issues-179 Fix tests --- tests/sqlite/table.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/sqlite/table.rs b/tests/sqlite/table.rs index 1fad76b67..34089a75d 100644 --- a/tests/sqlite/table.rs +++ b/tests/sqlite/table.rs @@ -321,10 +321,9 @@ fn drop_1() { assert_eq!( Table::drop() .table(Glyph::Table) - .table(Char::Table) .cascade() .to_string(SqliteQueryBuilder), - r#"DROP TABLE "glyph", "character""# + r#"DROP TABLE "glyph""# ); } From 5231edb6852ae3e788582fe095072549c10836cb Mon Sep 17 00:00:00 2001 From: Ivan Krivosheev Date: Mon, 26 Dec 2022 15:10:56 +0300 Subject: [PATCH 4/5] issues-179 Fix after merge conflict --- src/backend/mysql/view.rs | 6 ++--- src/backend/postgres/view.rs | 12 ++++++---- src/backend/sqlite/view.rs | 24 +++++++++++++++----- src/backend/view_builder.rs | 44 ++++++++++++++++++++++++------------ src/view/create.rs | 31 ++++++------------------- src/view/drop.rs | 24 ++++++-------------- src/view/rename.rs | 23 ++++++------------- 7 files changed, 79 insertions(+), 85 deletions(-) diff --git a/src/backend/mysql/view.rs b/src/backend/mysql/view.rs index 5c73ceb7f..e02173ab3 100644 --- a/src/backend/mysql/view.rs +++ b/src/backend/mysql/view.rs @@ -1,14 +1,14 @@ use crate::*; impl ViewBuilder for MysqlQueryBuilder { - fn prepare_view_rename_statement(&self, rename: &ViewRenameStatement, sql: &mut SqlWriter) { + fn prepare_view_rename_statement(&self, rename: &ViewRenameStatement, sql: &mut dyn SqlWriter) { write!(sql, "RENAME TABLE ").unwrap(); if let Some(from_name) = &rename.from_name { - from_name.prepare(sql, self.quote()); + from_name.prepare(sql.as_writer(), self.quote()); } write!(sql, " TO ").unwrap(); if let Some(to_name) = &rename.to_name { - to_name.prepare(sql, self.quote()); + to_name.prepare(sql.as_writer(), self.quote()); } } } diff --git a/src/backend/postgres/view.rs b/src/backend/postgres/view.rs index 8ac2fc265..cd96d7048 100644 --- a/src/backend/postgres/view.rs +++ b/src/backend/postgres/view.rs @@ -1,7 +1,11 @@ use crate::*; impl ViewBuilder for PostgresQueryBuilder { - fn prepare_view_create_befor_view(&self, create: &ViewCreateStatement, sql: &mut SqlWriter) { + fn prepare_view_create_befor_view( + &self, + create: &ViewCreateStatement, + sql: &mut dyn SqlWriter, + ) { if create.or_replace { write!(sql, " OR REPLACE").unwrap(); } @@ -15,14 +19,14 @@ impl ViewBuilder for PostgresQueryBuilder { } } - fn prepare_view_rename_statement(&self, rename: &ViewRenameStatement, sql: &mut SqlWriter) { + fn prepare_view_rename_statement(&self, rename: &ViewRenameStatement, sql: &mut dyn SqlWriter) { write!(sql, "ALTER VIEW ").unwrap(); if let Some(from_name) = &rename.from_name { - from_name.prepare(sql, self.quote()); + from_name.prepare(sql.as_writer(), self.quote()); } write!(sql, " TO ").unwrap(); if let Some(to_name) = &rename.to_name { - to_name.prepare(sql, self.quote()); + to_name.prepare(sql.as_writer(), self.quote()); } } } diff --git a/src/backend/sqlite/view.rs b/src/backend/sqlite/view.rs index fd5b60e45..2e0496475 100644 --- a/src/backend/sqlite/view.rs +++ b/src/backend/sqlite/view.rs @@ -1,28 +1,40 @@ use crate::*; impl ViewBuilder for SqliteQueryBuilder { - fn prepare_view_create_befor_view(&self, create: &ViewCreateStatement, sql: &mut SqlWriter) { + fn prepare_view_create_befor_view( + &self, + create: &ViewCreateStatement, + sql: &mut dyn SqlWriter, + ) { if create.temporary { write!(sql, " TEMPORARY").unwrap(); } } - fn prepare_view_create_after_view(&self, create: &ViewCreateStatement, sql: &mut SqlWriter) { + fn prepare_view_create_after_view( + &self, + create: &ViewCreateStatement, + sql: &mut dyn SqlWriter, + ) { if create.if_not_exists { write!(sql, " IF NOT EXISTS").unwrap(); } } - fn prepare_view_create_opt_update(&self, _opt: &ViewCreateOpt, _sql: &mut SqlWriter) { + fn prepare_view_create_opt_update(&self, _opt: &ViewCreateOpt, _sql: &mut dyn SqlWriter) { // SQLite does not support view create options } - fn prepare_view_rename_statement(&self, _rename: &ViewRenameStatement, _sql: &mut SqlWriter) { + fn prepare_view_rename_statement( + &self, + _rename: &ViewRenameStatement, + _sql: &mut dyn SqlWriter, + ) { // SQLite does not support rename view } /// Translate [`ViewDropStatement`] into SQL statement. - fn prepare_view_drop_statement(&self, drop: &ViewDropStatement, sql: &mut SqlWriter) { + fn prepare_view_drop_statement(&self, drop: &ViewDropStatement, sql: &mut dyn SqlWriter) { write!(sql, "DROP VIEW ").unwrap(); if drop.if_exists { @@ -31,7 +43,7 @@ impl ViewBuilder for SqliteQueryBuilder { self.prepare_view_ref(&drop.views[0], sql); } - fn prepare_view_drop_opt(&self, _drop_opt: &ViewDropOpt, _sql: &mut dyn std::fmt::Write) { + fn prepare_view_drop_opt(&self, _drop_opt: &ViewDropOpt, _sql: &mut dyn SqlWriter) { // SQLite does not support view drop options } } diff --git a/src/backend/view_builder.rs b/src/backend/view_builder.rs index d734f2326..a84fb7d94 100644 --- a/src/backend/view_builder.rs +++ b/src/backend/view_builder.rs @@ -2,7 +2,7 @@ use crate::*; pub trait ViewBuilder: QueryBuilder + QuotedBuilder { /// Translate [`ViewCreateStatement`] into SQL statement. - fn prepare_view_create_statement(&self, create: &ViewCreateStatement, sql: &mut SqlWriter) { + fn prepare_view_create_statement(&self, create: &ViewCreateStatement, sql: &mut dyn SqlWriter) { write!(sql, "CREATE").unwrap(); self.prepare_view_create_befor_view(create, sql); @@ -19,7 +19,7 @@ pub trait ViewBuilder: QueryBuilder + QuotedBuilder { if !first { write!(sql, ", ").unwrap(); } - column.prepare(sql, self.quote()); + column.prepare(sql.as_writer(), self.quote()); false }); write!(sql, " ) ").unwrap(); @@ -32,11 +32,21 @@ pub trait ViewBuilder: QueryBuilder + QuotedBuilder { } } - fn prepare_view_create_befor_view(&self, _create: &ViewCreateStatement, _sql: &mut SqlWriter) {} + fn prepare_view_create_befor_view( + &self, + _create: &ViewCreateStatement, + _sql: &mut dyn SqlWriter, + ) { + } - fn prepare_view_create_after_view(&self, _create: &ViewCreateStatement, _sql: &mut SqlWriter) {} + fn prepare_view_create_after_view( + &self, + _create: &ViewCreateStatement, + _sql: &mut dyn SqlWriter, + ) { + } - fn prepare_view_create_opt_update(&self, opt: &ViewCreateOpt, sql: &mut SqlWriter) { + fn prepare_view_create_opt_update(&self, opt: &ViewCreateOpt, sql: &mut dyn SqlWriter) { write!(sql, " WITH ").unwrap(); match opt { ViewCreateOpt::Cascade => write!(sql, "CASCADED").unwrap(), @@ -45,10 +55,14 @@ pub trait ViewBuilder: QueryBuilder + QuotedBuilder { write!(sql, " CHECK OPTION").unwrap(); } - fn prepare_view_rename_statement(&self, _rename: &ViewRenameStatement, _sql: &mut SqlWriter); + fn prepare_view_rename_statement( + &self, + _rename: &ViewRenameStatement, + _sql: &mut dyn SqlWriter, + ); /// Translate [`ViewDropStatement`] into SQL statement. - fn prepare_view_drop_statement(&self, drop: &ViewDropStatement, sql: &mut SqlWriter) { + fn prepare_view_drop_statement(&self, drop: &ViewDropStatement, sql: &mut dyn SqlWriter) { write!(sql, "DROP VIEW ").unwrap(); if drop.if_exists { @@ -72,7 +86,7 @@ pub trait ViewBuilder: QueryBuilder + QuotedBuilder { } /// Translate [`ViewDropOpt`] into SQL statement. - fn prepare_view_drop_opt(&self, drop_opt: &ViewDropOpt, sql: &mut dyn std::fmt::Write) { + fn prepare_view_drop_opt(&self, drop_opt: &ViewDropOpt, sql: &mut dyn SqlWriter) { write!( sql, "{}", @@ -85,22 +99,22 @@ pub trait ViewBuilder: QueryBuilder + QuotedBuilder { } /// Translate [`TableRef`] into SQL statement. - fn prepare_view_ref(&self, table_ref: &TableRef, sql: &mut SqlWriter) { + fn prepare_view_ref(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) { match table_ref { TableRef::Table(table) => { - table.prepare(sql, self.quote()); + table.prepare(sql.as_writer(), self.quote()); } TableRef::SchemaTable(schema, table) => { - schema.prepare(sql, self.quote()); + schema.prepare(sql.as_writer(), self.quote()); write!(sql, ".").unwrap(); - table.prepare(sql, self.quote()); + table.prepare(sql.as_writer(), self.quote()); } TableRef::DatabaseSchemaTable(database, schema, table) => { - database.prepare(sql, self.quote()); + database.prepare(sql.as_writer(), self.quote()); write!(sql, ".").unwrap(); - schema.prepare(sql, self.quote()); + schema.prepare(sql.as_writer(), self.quote()); write!(sql, ".").unwrap(); - table.prepare(sql, self.quote()); + table.prepare(sql.as_writer(), self.quote()); } _ => panic!("Not supported"), } diff --git a/src/view/create.rs b/src/view/create.rs index 3fda1813b..ba4b03b2d 100644 --- a/src/view/create.rs +++ b/src/view/create.rs @@ -1,6 +1,4 @@ -use crate::{ - backend::SchemaBuilder, prepare::*, query::SelectStatement, types::*, SchemaStatementBuilder, -}; +use crate::{backend::SchemaBuilder, query::SelectStatement, types::*, SchemaStatementBuilder}; /// Create a view /// @@ -8,7 +6,7 @@ use crate::{ /// /// ``` /// ``` -#[derive(Debug, Clone)] +#[derive(Default, Debug, Clone)] pub struct ViewCreateStatement { pub(crate) view: Option, pub(crate) columns: Vec, @@ -26,25 +24,10 @@ pub enum ViewCreateOpt { Local, } -impl Default for ViewCreateStatement { - fn default() -> Self { - Self::new() - } -} - impl ViewCreateStatement { /// Construct create view statement. pub fn new() -> Self { - Self { - view: None, - columns: Vec::new(), - query: SelectStatement::new(), - if_not_exists: false, - or_replace: false, - recursive: false, - temporary: false, - opt: None, - } + Self::default() } /// Create view if view not exists. @@ -140,14 +123,14 @@ impl ViewCreateStatement { impl SchemaStatementBuilder for ViewCreateStatement { fn build(&self, schema_builder: T) -> String { - let mut sql = SqlWriter::new(); + let mut sql = String::with_capacity(256); schema_builder.prepare_view_create_statement(self, &mut sql); - sql.result() + sql } fn build_any(&self, schema_builder: &dyn SchemaBuilder) -> String { - let mut sql = SqlWriter::new(); + let mut sql = String::with_capacity(256); schema_builder.prepare_view_create_statement(self, &mut sql); - sql.result() + sql } } diff --git a/src/view/drop.rs b/src/view/drop.rs index 38f5bc6a3..846d91b78 100644 --- a/src/view/drop.rs +++ b/src/view/drop.rs @@ -1,4 +1,4 @@ -use crate::{backend::SchemaBuilder, prepare::*, types::*, SchemaStatementBuilder}; +use crate::{backend::SchemaBuilder, types::*, SchemaStatementBuilder}; /// Drop a view /// @@ -6,7 +6,7 @@ use crate::{backend::SchemaBuilder, prepare::*, types::*, SchemaStatementBuilder /// /// ``` /// ``` -#[derive(Debug, Clone)] +#[derive(Default, Debug, Clone)] pub struct ViewDropStatement { pub(crate) views: Vec, pub(crate) options: Vec, @@ -20,20 +20,10 @@ pub enum ViewDropOpt { Cascade, } -impl Default for ViewDropStatement { - fn default() -> Self { - Self::new() - } -} - impl ViewDropStatement { /// Construct drop view statement. pub fn new() -> Self { - Self { - views: Vec::new(), - options: Vec::new(), - if_exists: false, - } + Self::default() } /// Set view name. @@ -74,14 +64,14 @@ impl ViewDropStatement { impl SchemaStatementBuilder for ViewDropStatement { fn build(&self, schema_builder: T) -> String { - let mut sql = SqlWriter::new(); + let mut sql = String::with_capacity(256); schema_builder.prepare_view_drop_statement(self, &mut sql); - sql.result() + sql } fn build_any(&self, schema_builder: &dyn SchemaBuilder) -> String { - let mut sql = SqlWriter::new(); + let mut sql = String::with_capacity(256); schema_builder.prepare_view_drop_statement(self, &mut sql); - sql.result() + sql } } diff --git a/src/view/rename.rs b/src/view/rename.rs index 9aa188503..162c2b56c 100644 --- a/src/view/rename.rs +++ b/src/view/rename.rs @@ -1,4 +1,4 @@ -use crate::{backend::SchemaBuilder, prepare::*, types::*, SchemaStatementBuilder}; +use crate::{backend::SchemaBuilder, types::*, SchemaStatementBuilder}; /// Rename a view /// @@ -6,25 +6,16 @@ use crate::{backend::SchemaBuilder, prepare::*, types::*, SchemaStatementBuilder /// /// ``` /// ``` -#[derive(Debug, Clone)] +#[derive(Default, Debug, Clone)] pub struct ViewRenameStatement { pub(crate) from_name: Option, pub(crate) to_name: Option, } -impl Default for ViewRenameStatement { - fn default() -> Self { - Self::new() - } -} - impl ViewRenameStatement { /// Construct rename view statement. pub fn new() -> Self { - Self { - from_name: None, - to_name: None, - } + Self::default() } /// Set old and new view name. @@ -48,14 +39,14 @@ impl ViewRenameStatement { impl SchemaStatementBuilder for ViewRenameStatement { fn build(&self, view_builder: T) -> String { - let mut sql = SqlWriter::new(); + let mut sql = String::with_capacity(256); view_builder.prepare_view_rename_statement(self, &mut sql); - sql.result() + sql } fn build_any(&self, view_builder: &dyn SchemaBuilder) -> String { - let mut sql = SqlWriter::new(); + let mut sql = String::with_capacity(256); view_builder.prepare_view_rename_statement(self, &mut sql); - sql.result() + sql } } From a29a9949893a1a22955059a324deecb5c0cac55f Mon Sep 17 00:00:00 2001 From: Jonas Weigand Date: Fri, 3 May 2024 23:57:01 +0200 Subject: [PATCH 5/5] issues-179 applied clippy fixes --- src/backend/query_builder.rs | 5 ++++- src/extension/postgres/mod.rs | 1 - src/query/returning.rs | 2 +- src/query/with.rs | 5 ++--- src/token.rs | 12 ++---------- src/types.rs | 2 +- 6 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/backend/query_builder.rs b/src/backend/query_builder.rs index cee45b9cd..635dc9289 100644 --- a/src/backend/query_builder.rs +++ b/src/backend/query_builder.rs @@ -993,7 +993,10 @@ pub trait QueryBuilder: QuotedBuilder + EscapeBuilder + TableRefBuilder { Value::Bytes(Some(v)) => write!( s, "x'{}'", - v.iter().map(|b| format!("{:02X}", b)).collect::() + v.iter().fold(String::new(), |mut output, b| { + let _ = write!(output, "{:02X}", b); + output + }) ) .unwrap(), #[cfg(feature = "with-json")] diff --git a/src/extension/postgres/mod.rs b/src/extension/postgres/mod.rs index f84241686..965ebd419 100644 --- a/src/extension/postgres/mod.rs +++ b/src/extension/postgres/mod.rs @@ -1,6 +1,5 @@ pub use expr::*; pub use func::*; -pub use interval::*; pub use types::*; use crate::types::BinOper; diff --git a/src/query/returning.rs b/src/query/returning.rs index c53039e2b..340113bb9 100644 --- a/src/query/returning.rs +++ b/src/query/returning.rs @@ -21,7 +21,7 @@ pub struct Returning; impl Returning { /// Constructs a new [`Returning`]. pub fn new() -> Self { - Self::default() + Self } /// Constructs a new [`ReturningClause::All`]. diff --git a/src/query/with.rs b/src/query/with.rs index 7650ea340..24074628b 100644 --- a/src/query/with.rs +++ b/src/query/with.rs @@ -11,7 +11,6 @@ use crate::SubQueryBuilder; use crate::SubQueryStatement; use crate::TableRef; use crate::{Alias, QueryBuilder}; -use std::ops::Deref; /// A table definition inside a WITH clause ([WithClause]). /// @@ -122,8 +121,8 @@ impl CommonTableExpression { pub fn from_select(select: SelectStatement) -> Self { let mut cte = Self::default(); cte.try_set_cols_from_selects(&select.selects); - if let Some(from) = select.from.get(0) { - match from.deref() { + if let Some(from) = select.from.first() { + match from { TableRef::Table(iden) => cte.set_table_name_from_select(iden), TableRef::SchemaTable(_, iden) => cte.set_table_name_from_select(iden), TableRef::DatabaseSchemaTable(_, _, iden) => cte.set_table_name_from_select(iden), diff --git a/src/token.rs b/src/token.rs index 4165f811b..2b3de2f3b 100644 --- a/src/token.rs +++ b/src/token.rs @@ -107,11 +107,7 @@ impl Tokenizer { self.inc(); } } else if !first { - if !escape && Self::is_escape_char(c) { - escape = true; - } else { - escape = false; - } + escape = !escape && Self::is_escape_char(c); write!(string, "{}", c).unwrap(); self.inc(); } else { @@ -149,11 +145,7 @@ impl Tokenizer { self.inc(); } } else if !first { - if !escape && Self::is_escape_char(c) { - escape = true; - } else { - escape = false; - } + escape = !escape && Self::is_escape_char(c); write!(string, "{}", c).unwrap(); self.inc(); } else { diff --git a/src/types.rs b/src/types.rs index 3d618c447..dddd461b6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -401,7 +401,7 @@ impl Iden for Alias { impl NullAlias { pub fn new() -> Self { - Self::default() + Self } }