Skip to content
Merged
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: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct SeaRc; // new
```
* `impl From<Expr> for Condition`. Now you can use that instead of
`ConditionExpression`, which has been removed.
* Addded `DatabaseName`, `SchemaName`, `TableName`, `ColumnName` types.

### Breaking Changes

Expand Down Expand Up @@ -120,6 +121,9 @@ impl Iden for Glyph {
}
}
```
* Reworked `TableRef` and `ColumnRef` variants.
* Turned `SchemaTable` into a type alias of `TableName`. Code that accesses the
fields inside may not compile. Other existing code should still compile.
* Removed `ConditionExpression` from the public API. Instead, just convert
between `Condition` and `Expr` using `From`/`Into`.
* Blanket-implemented `SqliteExpr` and `PgExpr` for `T where T: ExprTrait`.
Expand Down
8 changes: 1 addition & 7 deletions src/audit/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@ pub(super) fn parse_audit_table(table_ref: &TableRef) -> Option<SchemaTable> {
match table_ref {
TableRef::SubQuery(_, _) => None,
TableRef::FunctionCall(_, _) => None,
TableRef::Table(tbl) | TableRef::TableAlias(tbl, _) => Some(SchemaTable(None, tbl.clone())),
TableRef::SchemaTable(sch, tbl)
| TableRef::DatabaseSchemaTable(_, sch, tbl)
| TableRef::SchemaTableAlias(sch, tbl, _)
| TableRef::DatabaseSchemaTableAlias(_, sch, tbl, _) => {
Some(SchemaTable(Some(sch.clone()), tbl.clone()))
}
TableRef::Table(tbl, _) => Some(tbl.clone()),
TableRef::ValuesList(_, _) => None,
}
}
14 changes: 10 additions & 4 deletions src/audit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod insert;
mod select;
mod update;

use crate::DynIden;
use crate::{DynIden, TableName};

pub trait AuditTrait {
fn audit(&self) -> Result<QueryAccessAudit, Error>;
Expand All @@ -25,7 +25,10 @@ pub struct QueryAccessAudit {
#[non_exhaustive]
pub struct QueryAccessRequest {
pub access_type: AccessType,
pub schema_table: SchemaTable,
/// Legacy naming, kept for compatibility. It should be `table_name`.
///
/// The table name can be qualified as `(database.)(schema.)table`.
pub schema_table: TableName,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
Expand All @@ -47,8 +50,11 @@ pub enum SchemaOper {
Truncate,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SchemaTable(pub Option<DynIden>, pub DynIden);
/// A table name, optionally qualified as `(database.)(schema.)table`.
///
/// This is a legacy type alias, to preserve some compatibility.
/// It's going to be deprecated in the future.
pub type SchemaTable = TableName;

impl QueryAccessAudit {
/// This filters the selects from access requests.
Expand Down
15 changes: 3 additions & 12 deletions src/audit/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,10 @@ impl Walker {
match table_ref {
TableRef::SubQuery(select, _) => self.recurse_audit_select(select)?,
TableRef::FunctionCall(function, _) => self.recurse_audit_function(function)?,
TableRef::Table(tbl) | TableRef::TableAlias(tbl, _) => {
TableRef::Table(table_name, _) => {
self.access.push(QueryAccessRequest {
access_type: AccessType::Select,
schema_table: SchemaTable(None, tbl.clone()),
});
}
TableRef::SchemaTable(sch, tbl)
| TableRef::DatabaseSchemaTable(_, sch, tbl)
| TableRef::SchemaTableAlias(sch, tbl, _)
| TableRef::DatabaseSchemaTableAlias(_, sch, tbl, _) => {
self.access.push(QueryAccessRequest {
access_type: AccessType::Select,
schema_table: SchemaTable(Some(sch.clone()), tbl.clone()),
schema_table: table_name.clone(),
});
}
TableRef::ValuesList(_, _) => (),
Expand Down Expand Up @@ -179,7 +170,7 @@ impl Walker {
// remove cte alias
for cte in &with_clause.cte_expressions {
if let Some(table_name) = &cte.table_name {
self.remove_item(AccessType::Select, &SchemaTable(None, table_name.clone()));
self.remove_item(AccessType::Select, &TableName(None, table_name.clone()));
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/backend/mysql/foreign_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use super::*;
impl ForeignKeyBuilder for MysqlQueryBuilder {
fn prepare_table_ref_fk_stmt(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
match table_ref {
TableRef::Table(_) => self.prepare_table_ref_iden(table_ref, sql),
// Support only "naked" table names with no schema or alias.
TableRef::Table(TableName(None, _), None) => {
self.prepare_table_ref_iden(table_ref, sql)
}
_ => panic!("Not supported"),
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/backend/mysql/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ impl IndexBuilder for MysqlQueryBuilder {

fn prepare_table_ref_index_stmt(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
match table_ref {
TableRef::Table(_) => self.prepare_table_ref_iden(table_ref, sql),
// Support only "naked" table names with no schema or alias.
TableRef::Table(TableName(None, _), None) => {
self.prepare_table_ref_iden(table_ref, sql)
}
_ => panic!("Not supported"),
}
}
Expand Down
9 changes: 4 additions & 5 deletions src/backend/mysql/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,10 @@ impl QueryBuilder for MysqlQueryBuilder {
self.prepare_iden(column, sql);
} else {
if let Some(table) = table {
if let TableRef::Table(table) = table.deref() {
self.prepare_column_ref(
&ColumnRef::TableColumn(table.clone(), column.clone()),
sql,
);
// Support only "naked" table names with no schema or alias.
if let TableRef::Table(TableName(None, table), None) = table.deref() {
let column_name = ColumnName::from((table.clone(), column.clone()));
self.prepare_column_ref(&ColumnRef::Column(column_name), sql);
return;
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/backend/postgres/foreign_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,8 @@ impl ForeignKeyBuilder for PostgresQueryBuilder {

fn prepare_table_ref_fk_stmt(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
match table_ref {
TableRef::Table(_)
| TableRef::SchemaTable(_, _)
| TableRef::DatabaseSchemaTable(_, _, _) => self.prepare_table_ref_iden(table_ref, sql),
// Support only unaliased (but potentialy qualified) table names.
TableRef::Table(.., None) => self.prepare_table_ref_iden(table_ref, sql),
_ => panic!("Not supported"),
}
}
Expand Down
26 changes: 17 additions & 9 deletions src/backend/postgres/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,14 @@ impl IndexBuilder for PostgresQueryBuilder {
}

fn prepare_table_ref_index_stmt(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
match table_ref {
TableRef::Table(_) | TableRef::SchemaTable(_, _) => {
self.prepare_table_ref_iden(table_ref, sql)
}
_ => panic!("Not supported"),
// Support only `table` and `schema.table` forms.
// No `database.schema.table` or aliases.
let TableRef::Table(table_name, None) = table_ref else {
panic!("Not supported");
};
match table_name.as_iden_tuple() {
(Some(_db), _schema, _table) => panic!("Not supported"),
(None, _schema, _table) => self.prepare_table_ref_iden(table_ref, sql),
}
}

Expand All @@ -94,13 +97,18 @@ impl IndexBuilder for PostgresQueryBuilder {
}

if let Some(table) = &drop.table {
match table {
TableRef::Table(_) => {}
TableRef::SchemaTable(schema, _) => {
// Support only `table` and `schema.table` forms.
// No `database.schema.table` or aliases.
let TableRef::Table(table_name, None) = table else {
panic!("Not supported");
};
match table_name.as_iden_tuple() {
(None, None, _table) => {}
(None, Some(schema), _table) => {
self.prepare_iden(schema, sql);
write!(sql, ".").unwrap();
}
_ => panic!("Not supported"),
(Some(_db), _schema, _table) => panic!("Not supported"),
}
}
if let Some(name) = &drop.index.name {
Expand Down
28 changes: 11 additions & 17 deletions src/backend/query_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,27 +595,21 @@ pub trait QueryBuilder:

fn prepare_column_ref(&self, column_ref: &ColumnRef, sql: &mut dyn SqlWriter) {
match column_ref {
ColumnRef::Column(column) => self.prepare_iden(column, sql),
ColumnRef::TableColumn(table, column) => {
self.prepare_iden(table, sql);
write!(sql, ".").unwrap();
self.prepare_iden(column, sql);
}
ColumnRef::SchemaTableColumn(schema, table, column) => {
self.prepare_iden(schema, sql);
write!(sql, ".").unwrap();
self.prepare_iden(table, sql);
write!(sql, ".").unwrap();
ColumnRef::Column(ColumnName(table_name, column)) => {
if let Some(table_name) = table_name {
self.prepare_table_name(table_name, sql);
write!(sql, ".").unwrap();
}
self.prepare_iden(column, sql);
}
ColumnRef::Asterisk => {
ColumnRef::Asterisk(table_name) => {
if let Some(table_name) = table_name {
self.prepare_table_name(table_name, sql);
write!(sql, ".").unwrap();
}
write!(sql, "*").unwrap();
}
ColumnRef::TableAsterisk(table) => {
self.prepare_iden(table, sql);
write!(sql, ".*").unwrap();
}
};
}
}

/// Translate [`UnOper`] into SQL statement.
Expand Down
5 changes: 4 additions & 1 deletion src/backend/sqlite/foreign_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use super::*;
impl ForeignKeyBuilder for SqliteQueryBuilder {
fn prepare_table_ref_fk_stmt(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
match table_ref {
TableRef::Table(_) => self.prepare_table_ref_iden(table_ref, sql),
// Support only "naked" table names with no schema or alias.
TableRef::Table(TableName(None, _), None) => {
self.prepare_table_ref_iden(table_ref, sql)
}
_ => panic!("Not supported"),
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/backend/sqlite/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ impl IndexBuilder for SqliteQueryBuilder {

fn prepare_table_ref_index_stmt(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
match table_ref {
TableRef::Table(_) => self.prepare_table_ref_iden(table_ref, sql),
// Support only "naked" table names with no schema or alias.
TableRef::Table(TableName(None, _), None) => {
self.prepare_table_ref_iden(table_ref, sql)
}
_ => panic!("Not supported"),
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/backend/table_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,8 @@ pub trait TableBuilder:
/// Translate [`TableRef`] into SQL statement.
fn prepare_table_ref_table_stmt(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
match table_ref {
TableRef::Table(_)
| TableRef::SchemaTable(_, _)
| TableRef::DatabaseSchemaTable(_, _, _) => self.prepare_table_ref_iden(table_ref, sql),
// Support only unaliased (but potentialy qualified) table names.
TableRef::Table(.., None) => self.prepare_table_ref_iden(table_ref, sql),
_ => panic!("Not supported"),
}
}
Expand Down
60 changes: 21 additions & 39 deletions src/backend/table_ref_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,30 @@ use crate::*;
pub trait TableRefBuilder: QuotedBuilder {
/// Translate [`TableRef`] that without values into SQL statement.
fn prepare_table_ref_iden(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
match table_ref {
TableRef::Table(iden) => {
self.prepare_iden(iden, sql);
}
TableRef::SchemaTable(schema, table) => {
self.prepare_iden(schema, sql);
write!(sql, ".").unwrap();
self.prepare_iden(table, sql);
}
TableRef::DatabaseSchemaTable(database, schema, table) => {
self.prepare_iden(database, sql);
write!(sql, ".").unwrap();
self.prepare_iden(schema, sql);
write!(sql, ".").unwrap();
self.prepare_iden(table, sql);
}
TableRef::TableAlias(iden, alias) => {
self.prepare_iden(iden, sql);
write!(sql, " AS ").unwrap();
self.prepare_iden(alias, sql);
}
TableRef::SchemaTableAlias(schema, table, alias) => {
self.prepare_iden(schema, sql);
write!(sql, ".").unwrap();
self.prepare_iden(table, sql);
write!(sql, " AS ").unwrap();
self.prepare_iden(alias, sql);
}
TableRef::DatabaseSchemaTableAlias(database, schema, table, alias) => {
self.prepare_iden(database, sql);
write!(sql, ".").unwrap();
self.prepare_iden(schema, sql);
write!(sql, ".").unwrap();
self.prepare_iden(table, sql);
write!(sql, " AS ").unwrap();
self.prepare_iden(alias, sql);
}
let (table_name, alias) = match table_ref {
TableRef::Table(table_name, alias) => (table_name, alias),
TableRef::SubQuery(_, _)
| TableRef::ValuesList(_, _)
| TableRef::FunctionCall(_, _) => {
panic!("TableRef with values is not support")
| TableRef::FunctionCall(_, _) => panic!("TableRef with values is not support"),
};
self.prepare_table_name(table_name, sql);
if let Some(alias) = alias {
write!(sql, " AS ").unwrap();
self.prepare_iden(alias, sql);
}
}

/// Translate [`TableName`] into an SQL statement.
fn prepare_table_name(&self, table_name: &TableName, sql: &mut dyn SqlWriter) {
let TableName(schema_name, table) = table_name;
if let Some(SchemaName(database_name, schema)) = schema_name {
if let Some(DatabaseName(database)) = database_name {
self.prepare_iden(database, sql);
write!(sql, ".").unwrap();
}
self.prepare_iden(schema, sql);
write!(sql, ".").unwrap();
}
self.prepare_iden(table, sql);
}
}
17 changes: 7 additions & 10 deletions src/query/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -987,10 +987,7 @@ impl SelectStatement {
/// );
/// assert_eq!(
/// query.audit().unwrap().selects(),
/// [SchemaTable(
/// Some(Font::Table.into_iden()),
/// Char::Table.into_iden()
/// )]
/// [TableName(Some(Font::Table.into()), Char::Table.into_iden())]
/// );
/// ```
pub fn from_as<R, A>(&mut self, tbl_ref: R, alias: A) -> &mut Self
Expand Down Expand Up @@ -1051,7 +1048,7 @@ impl SelectStatement {
/// use sea_query::{tests_cfg::*, *};
///
/// let query = Query::select()
/// .column(ColumnRef::Asterisk)
/// .column(Asterisk)
/// .from_function(Func::random(), "func")
/// .to_owned();
///
Expand Down Expand Up @@ -1083,7 +1080,7 @@ impl SelectStatement {
/// use sea_query::{tests_cfg::*, *};
///
/// let query = Query::select()
/// .column(ColumnRef::Asterisk)
/// .column(Asterisk)
/// .from(Char::Table)
/// .from_clear()
/// .from(Font::Table)
Expand Down Expand Up @@ -2365,14 +2362,14 @@ impl SelectStatement {
/// .to_owned();
///
/// let select = SelectStatement::new()
/// .column(ColumnRef::Asterisk)
/// .column(Asterisk)
/// .from("cte_traversal")
/// .to_owned();
///
/// let with_clause = WithClause::new()
/// .recursive(true)
/// .cte(common_table_expression)
/// .cycle(Cycle::new_from_expr_set_using(Expr::Column(ColumnRef::Column("id".into_iden())), "looped", "traversal_path"))
/// .cycle(Cycle::new_from_expr_set_using(Expr::Column("id".into_column_ref()), "looped", "traversal_path"))
/// .to_owned();
///
/// let query = select.with(with_clause).to_owned();
Expand Down Expand Up @@ -2437,11 +2434,11 @@ impl SelectStatement {
/// let with_clause = WithClause::new()
/// .recursive(true)
/// .cte(common_table_expression)
/// .cycle(Cycle::new_from_expr_set_using(Expr::Column(ColumnRef::Column("id".into_iden())), "looped", "traversal_path"))
/// .cycle(Cycle::new_from_expr_set_using(Expr::Column("id".into_column_ref()), "looped", "traversal_path"))
/// .to_owned();
///
/// let query = SelectStatement::new()
/// .column(ColumnRef::Asterisk)
/// .column(Asterisk)
/// .from("cte_traversal")
/// .with_cte(with_clause)
/// .to_owned();
Expand Down
Loading