sea_orm/database/
statement.rs1use crate::DbBackend;
2use sea_query::{inject_parameters, MysqlQueryBuilder, PostgresQueryBuilder, SqliteQueryBuilder};
3pub use sea_query::{Value, Values};
4use std::fmt;
5
6#[derive(Debug, Clone, PartialEq)]
8pub struct Statement {
9 pub sql: String,
11 pub values: Option<Values>,
13 pub db_backend: DbBackend,
16}
17
18pub trait StatementBuilder {
20 fn build(&self, db_backend: &DbBackend) -> Statement;
22}
23
24impl Statement {
25 pub fn from_string<T>(db_backend: DbBackend, stmt: T) -> Statement
27 where
28 T: Into<String>,
29 {
30 Statement {
31 sql: stmt.into(),
32 values: None,
33 db_backend,
34 }
35 }
36
37 pub fn from_sql_and_values<I, T>(db_backend: DbBackend, sql: T, values: I) -> Self
40 where
41 I: IntoIterator<Item = Value>,
42 T: Into<String>,
43 {
44 Self::from_string_values_tuple(db_backend, (sql, Values(values.into_iter().collect())))
45 }
46
47 pub(crate) fn from_string_values_tuple<T>(db_backend: DbBackend, stmt: (T, Values)) -> Statement
48 where
49 T: Into<String>,
50 {
51 Statement {
52 sql: stmt.0.into(),
53 values: Some(stmt.1),
54 db_backend,
55 }
56 }
57}
58
59impl fmt::Display for Statement {
60 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61 match &self.values {
62 Some(values) => {
63 let string = inject_parameters(
64 &self.sql,
65 values.0.clone(),
66 self.db_backend.get_query_builder().as_ref(),
67 );
68 write!(f, "{}", &string)
69 }
70 None => {
71 write!(f, "{}", &self.sql)
72 }
73 }
74 }
75}
76
77macro_rules! build_any_stmt {
78 ($stmt: expr, $db_backend: expr) => {
79 match $db_backend {
80 DbBackend::MySql => $stmt.build(MysqlQueryBuilder),
81 DbBackend::Postgres => $stmt.build(PostgresQueryBuilder),
82 DbBackend::Sqlite => $stmt.build(SqliteQueryBuilder),
83 }
84 };
85}
86
87macro_rules! build_postgres_stmt {
88 ($stmt: expr, $db_backend: expr) => {
89 match $db_backend {
90 DbBackend::Postgres => $stmt.to_string(PostgresQueryBuilder),
91 DbBackend::MySql | DbBackend::Sqlite => unimplemented!(),
92 }
93 };
94}
95
96macro_rules! build_query_stmt {
97 ($stmt: ty) => {
98 impl StatementBuilder for $stmt {
99 fn build(&self, db_backend: &DbBackend) -> Statement {
100 let stmt = build_any_stmt!(self, db_backend);
101 Statement::from_string_values_tuple(*db_backend, stmt)
102 }
103 }
104 };
105}
106
107build_query_stmt!(sea_query::InsertStatement);
108build_query_stmt!(sea_query::SelectStatement);
109build_query_stmt!(sea_query::UpdateStatement);
110build_query_stmt!(sea_query::DeleteStatement);
111build_query_stmt!(sea_query::WithQuery);
112
113macro_rules! build_schema_stmt {
114 ($stmt: ty) => {
115 impl StatementBuilder for $stmt {
116 fn build(&self, db_backend: &DbBackend) -> Statement {
117 let stmt = build_any_stmt!(self, db_backend);
118 Statement::from_string(*db_backend, stmt)
119 }
120 }
121 };
122}
123
124build_schema_stmt!(sea_query::TableCreateStatement);
125build_schema_stmt!(sea_query::TableDropStatement);
126build_schema_stmt!(sea_query::TableAlterStatement);
127build_schema_stmt!(sea_query::TableRenameStatement);
128build_schema_stmt!(sea_query::TableTruncateStatement);
129build_schema_stmt!(sea_query::IndexCreateStatement);
130build_schema_stmt!(sea_query::IndexDropStatement);
131build_schema_stmt!(sea_query::ForeignKeyCreateStatement);
132build_schema_stmt!(sea_query::ForeignKeyDropStatement);
133
134macro_rules! build_type_stmt {
135 ($stmt: ty) => {
136 impl StatementBuilder for $stmt {
137 fn build(&self, db_backend: &DbBackend) -> Statement {
138 let stmt = build_postgres_stmt!(self, db_backend);
139 Statement::from_string(*db_backend, stmt)
140 }
141 }
142 };
143}
144
145build_type_stmt!(sea_query::extension::postgres::TypeAlterStatement);
146build_type_stmt!(sea_query::extension::postgres::TypeCreateStatement);
147build_type_stmt!(sea_query::extension::postgres::TypeDropStatement);