Skip to content

Commit

Permalink
issues-179 Add backend generators
Browse files Browse the repository at this point in the history
  • Loading branch information
ikrivosheev committed Apr 5, 2022
1 parent 842e6d3 commit 160b7bd
Show file tree
Hide file tree
Showing 12 changed files with 245 additions and 21 deletions.
13 changes: 12 additions & 1 deletion src/backend/mysql/view.rs
Original file line number Diff line number Diff line change
@@ -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());
}
}
}
27 changes: 26 additions & 1 deletion src/backend/postgres/view.rs
Original file line number Diff line number Diff line change
@@ -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());
}
}
}
12 changes: 12 additions & 0 deletions src/backend/sqlite/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,18 @@ impl TableBuilder for SqliteQueryBuilder {
.unwrap()
}

/// Translate [`TableDropStatement`] into SQL statement.
fn prepare_table_drop_statement(&self, drop: &TableDropStatement, sql: &mut SqlWriter) {
write!(sql, "DROP TABLE ").unwrap();

if drop.if_exists {
write!(sql, "IF EXISTS ").unwrap();
}

// SQLite does not support drop many tables
TableBuilder::prepare_table_ref(self, &drop.tables[0], sql);
}

fn prepare_table_drop_opt(&self, _drop_opt: &TableDropOpt, _sql: &mut dyn std::fmt::Write) {
// SQLite does not support table drop options
}
Expand Down
34 changes: 33 additions & 1 deletion src/backend/sqlite/view.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
105 changes: 102 additions & 3 deletions src/backend/view_builder.rs
Original file line number Diff line number Diff line change
@@ -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"),
}
}
}
4 changes: 3 additions & 1 deletion src/query/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
types::*,
value::*,
Query, QueryStatementBuilder, QueryStatementWriter, SelectExpr, SelectStatement,
SubQueryStatement, WithClause, WithQuery,
SubQueryBuilder, SubQueryStatement, WithClause, WithQuery,
};

/// Delete existing rows from the table
Expand Down Expand Up @@ -227,7 +227,9 @@ impl QueryStatementBuilder for DeleteStatement {
) {
query_builder.prepare_delete_statement(self, sql, collector);
}
}

impl SubQueryBuilder for DeleteStatement {
fn into_sub_query_statement(self) -> SubQueryStatement {
SubQueryStatement::DeleteStatement(self)
}
Expand Down
4 changes: 3 additions & 1 deletion 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::*, value::*, Expr, OnConflict, Query,
QueryStatementBuilder, QueryStatementWriter, SelectExpr, SelectStatement, SimpleExpr,
SubQueryStatement, WithClause, WithQuery,
SubQueryBuilder, SubQueryStatement, WithClause, WithQuery,
};

/// Represents a value source that can be used in an insert query.
Expand Down Expand Up @@ -438,7 +438,9 @@ impl QueryStatementBuilder for InsertStatement {
) {
query_builder.prepare_insert_statement(self, sql, collector);
}
}

impl SubQueryBuilder for InsertStatement {
fn into_sub_query_statement(self) -> SubQueryStatement {
SubQueryStatement::InsertStatement(self)
}
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::*,
QueryStatementBuilder, QueryStatementWriter, SubQueryStatement, WindowStatement, WithClause,
WithQuery,
QueryStatementBuilder, QueryStatementWriter, SubQueryBuilder, SubQueryStatement,
WindowStatement, WithClause, WithQuery,
};

/// Select rows from an existing table
Expand Down Expand Up @@ -2121,7 +2121,9 @@ impl QueryStatementBuilder for SelectStatement {
) {
query_builder.prepare_select_statement(self, sql, collector);
}
}

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 @@ -33,7 +33,9 @@ pub trait QueryStatementBuilder: Debug {
sql: &mut SqlWriter,
collector: &mut dyn FnMut(Value),
);
}

pub trait SubQueryBuilder: Debug {
fn into_sub_query_statement(self) -> SubQueryStatement;
}

Expand Down
4 changes: 3 additions & 1 deletion src/query/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
types::*,
value::*,
Query, QueryStatementBuilder, QueryStatementWriter, SelectExpr, SelectStatement,
SubQueryStatement, WithClause, WithQuery,
SubQueryBuilder, SubQueryStatement, WithClause, WithQuery,
};

/// Update existing rows in the table
Expand Down Expand Up @@ -356,7 +356,9 @@ impl QueryStatementBuilder for UpdateStatement {
) {
query_builder.prepare_update_statement(self, sql, collector);
}
}

impl SubQueryBuilder for UpdateStatement {
fn into_sub_query_statement(self) -> SubQueryStatement {
SubQueryStatement::UpdateStatement(self)
}
Expand Down
9 changes: 6 additions & 3 deletions src/query/with.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::Value;
Expand Down Expand Up @@ -110,7 +111,7 @@ impl CommonTableExpression {
/// columns.
pub fn query<Q>(&mut self, query: Q) -> &mut Self
where
Q: QueryStatementBuilder,
Q: SubQueryBuilder,
{
self.query = Some(Box::new(query.into_sub_query_statement()));
self
Expand Down Expand Up @@ -492,7 +493,7 @@ impl WithClause {
/// execute the argument query with this WITH clause.
pub fn query<T>(self, query: T) -> WithQuery
where
T: QueryStatementBuilder + 'static,
T: SubQueryBuilder + 'static,
{
WithQuery::new().with_clause(self).query(query).to_owned()
}
Expand Down Expand Up @@ -583,7 +584,7 @@ impl WithQuery {
/// Set the query that you execute with the [WithClause].
pub fn query<T>(&mut self, query: T) -> &mut Self
where
T: QueryStatementBuilder,
T: SubQueryBuilder,
{
self.query = Some(Box::new(query.into_sub_query_statement()));
self
Expand All @@ -599,7 +600,9 @@ impl QueryStatementBuilder for WithQuery {
) {
query_builder.prepare_with_query(self, sql, collector);
}
}

impl SubQueryBuilder for WithQuery {
fn into_sub_query_statement(self) -> SubQueryStatement {
SubQueryStatement::WithStatement(self)
}
Expand Down
Loading

0 comments on commit 160b7bd

Please sign in to comment.