Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issues-179 Add support for view #293

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions src/backend/mysql/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;

Expand Down
14 changes: 14 additions & 0 deletions src/backend/mysql/view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::*;

impl ViewBuilder for MysqlQueryBuilder {
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.as_writer(), self.quote());
}
write!(sql, " TO ").unwrap();
if let Some(to_name) = &rename.to_name {
to_name.prepare(sql.as_writer(), self.quote());
}
}
}
1 change: 1 addition & 0 deletions src/backend/postgres/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;

Expand Down
32 changes: 32 additions & 0 deletions src/backend/postgres/view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use crate::*;

impl ViewBuilder for PostgresQueryBuilder {
fn prepare_view_create_befor_view(
&self,
create: &ViewCreateStatement,
sql: &mut dyn 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 dyn SqlWriter) {
write!(sql, "ALTER VIEW ").unwrap();
if let Some(from_name) = &rename.from_name {
from_name.prepare(sql.as_writer(), self.quote());
}
write!(sql, " TO ").unwrap();
if let Some(to_name) = &rename.to_name {
to_name.prepare(sql.as_writer(), self.quote());
}
}
}
5 changes: 4 additions & 1 deletion src/backend/query_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<String>()
v.iter().fold(String::new(), |mut output, b| {
let _ = write!(output, "{:02X}", b);
output
})
)
.unwrap(),
#[cfg(feature = "with-json")]
Expand Down
1 change: 1 addition & 0 deletions src/backend/sqlite/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;

Expand Down
49 changes: 49 additions & 0 deletions src/backend/sqlite/view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::*;

impl ViewBuilder for SqliteQueryBuilder {
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 dyn SqlWriter,
) {
if create.if_not_exists {
write!(sql, " IF NOT EXISTS").unwrap();
}
}

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 dyn SqlWriter,
) {
// SQLite does not support rename view
}

/// Translate [`ViewDropStatement`] into SQL statement.
fn prepare_view_drop_statement(&self, drop: &ViewDropStatement, sql: &mut dyn 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 SqlWriter) {
// SQLite does not support view drop options
}
}
122 changes: 122 additions & 0 deletions src/backend/view_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
use crate::*;

pub trait ViewBuilder: QueryBuilder + QuotedBuilder {
/// Translate [`ViewCreateStatement`] into SQL statement.
fn prepare_view_create_statement(&self, create: &ViewCreateStatement, sql: &mut dyn SqlWriter) {
write!(sql, "CREATE").unwrap();
self.prepare_view_create_befor_view(create, sql);

write!(sql, " VIEW ").unwrap();
self.prepare_view_create_after_view(create, sql);

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.as_writer(), 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 dyn 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 dyn 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 dyn SqlWriter,
);

/// Translate [`ViewDropStatement`] into SQL statement.
fn prepare_view_drop_statement(&self, drop: &ViewDropStatement, sql: &mut dyn 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 SqlWriter) {
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 dyn SqlWriter) {
match table_ref {
TableRef::Table(table) => {
table.prepare(sql.as_writer(), self.quote());
}
TableRef::SchemaTable(schema, table) => {
schema.prepare(sql.as_writer(), self.quote());
write!(sql, ".").unwrap();
table.prepare(sql.as_writer(), self.quote());
}
TableRef::DatabaseSchemaTable(database, schema, table) => {
database.prepare(sql.as_writer(), self.quote());
write!(sql, ".").unwrap();
schema.prepare(sql.as_writer(), self.quote());
write!(sql, ".").unwrap();
table.prepare(sql.as_writer(), self.quote());
}
_ => panic!("Not supported"),
}
}
}
1 change: 0 additions & 1 deletion src/extension/postgres/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pub use expr::*;
pub use func::*;
pub use interval::*;
pub use types::*;

use crate::types::BinOper;
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand All @@ -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};
Expand Down
6 changes: 4 additions & 2 deletions src/query/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
Expand Down
14 changes: 8 additions & 6 deletions src/query/insert.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -521,14 +521,16 @@ 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 {
fn build_collect_into<T: QueryBuilder>(&self, query_builder: T, sql: &mut dyn SqlWriter) {
query_builder.prepare_insert_statement(self, sql);
}
}

impl SubQueryBuilder for InsertStatement {
fn into_sub_query_statement(self) -> SubQueryStatement {
SubQueryStatement::InsertStatement(self)
}
}
2 changes: 1 addition & 1 deletion src/query/returning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`].
Expand Down
6 changes: 4 additions & 2 deletions src/query/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
Expand Down
2 changes: 2 additions & 0 deletions src/query/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Loading