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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pub struct TableName(pub Option<SchemaName>, pub DynIden);

* Enable `clippy::nursery` https://github.com/SeaQL/sea-query/pull/938
* Removed unnecessary `'static` bounds from type signatures https://github.com/SeaQL/sea-query/pull/921
* `cast_as_quoted` now allows you to [qualify the type
name](https://github.com/SeaQL/sea-query/issues/827).
* Most `Value` variants are now unboxed (except `BigDecimal` and `Array`). Previously the size is 24 bytes. https://github.com/SeaQL/sea-query/pull/925
```rust
assert_eq!(std::mem::size_of::<Value>(), 32);
Expand Down Expand Up @@ -96,6 +98,11 @@ assert_eq!(

### Breaking Changes

* Changed `Expr::TypeName(DynIden)` to `Expr::TypeName(TypeName)`, which can be
[qualified](https://github.com/SeaQL/sea-query/issues/827).

If you manually construct this variant and it no longer compiles, just add
`.into()`.
* Removed inherent `SimpleExpr` methods that duplicate `ExprTrait`. If you encounter the following error, please add `use sea_query::ExprTrait` in scope https://github.com/SeaQL/sea-query/pull/890
```rust
error[E0599]: no method named `like` found for enum `sea_query::Expr` in the current scope
Expand Down
14 changes: 12 additions & 2 deletions src/backend/query_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,8 @@ pub trait QueryBuilder:
Expr::Constant(val) => {
self.prepare_constant(val, sql);
}
Expr::TypeName(iden) => {
self.prepare_iden(iden, sql);
Expr::TypeName(type_name) => {
self.prepare_type_name(type_name, sql);
}
}
}
Expand Down Expand Up @@ -910,6 +910,16 @@ pub trait QueryBuilder:
self.prepare_function_name_common(function, sql)
}

/// Translate [`TypeName`] into an SQL statement.
fn prepare_type_name(&self, type_name: &TypeName, sql: &mut dyn SqlWriter) {
let TypeName(schema_name, r#type) = type_name;
if let Some(schema_name) = schema_name {
self.prepare_schema_name(schema_name, sql);
write!(sql, ".").unwrap();
}
self.prepare_iden(r#type, sql);
}

/// Translate [`JoinType`] into SQL statement.
fn prepare_join_type(&self, join_type: &JoinType, sql: &mut dyn SqlWriter) {
self.prepare_join_type_common(join_type, sql)
Expand Down
18 changes: 12 additions & 6 deletions src/backend/table_ref_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@ pub trait TableRefBuilder: QuotedBuilder {
/// 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);
if let Some(schema_name) = schema_name {
self.prepare_schema_name(schema_name, sql);
write!(sql, ".").unwrap();
}
self.prepare_iden(table, sql);
}

/// Translate [`SchemaName`] into an SQL statement.
fn prepare_schema_name(&self, schema_name: &SchemaName, sql: &mut dyn SqlWriter) {
let 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);
}
}
2 changes: 1 addition & 1 deletion src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub enum Expr {
AsEnum(DynIden, Box<Expr>),
Case(Box<CaseStatement>),
Constant(Value),
TypeName(DynIden),
TypeName(TypeName),
}

/// "Operator" methods for building expressions.
Expand Down
28 changes: 24 additions & 4 deletions src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,8 @@ impl Func {

/// Call `CAST` function with a case-sensitive custom type.
///
/// Type can be qualified with a schema name.
///
/// # Examples
///
/// ```
Expand All @@ -497,15 +499,33 @@ impl Func {
/// query.to_string(SqliteQueryBuilder),
/// r#"SELECT CAST('hello' AS "MyType")"#
/// );
///
/// // Also works with a schema-qualified type name:
///
/// let query = Query::select()
/// .expr(Func::cast_as_quoted("hello", ("MySchema", "MyType")))
/// .to_owned();
///
/// assert_eq!(
/// query.to_string(MysqlQueryBuilder),
/// r#"SELECT CAST('hello' AS `MySchema`.`MyType`)"#
/// );
/// assert_eq!(
/// query.to_string(PostgresQueryBuilder),
/// r#"SELECT CAST('hello' AS "MySchema"."MyType")"#
/// );
/// assert_eq!(
/// query.to_string(SqliteQueryBuilder),
/// r#"SELECT CAST('hello' AS "MySchema"."MyType")"#
/// );
/// ```
pub fn cast_as_quoted<V, I>(expr: V, iden: I) -> FunctionCall
pub fn cast_as_quoted<V, I>(expr: V, r#type: I) -> FunctionCall
where
V: Into<Expr>,
I: IntoIden,
I: Into<TypeName>,
{
let expr: Expr = expr.into();
FunctionCall::new(Func::Cast)
.arg(expr.binary(BinOper::As, Expr::TypeName(iden.into_iden())))
FunctionCall::new(Func::Cast).arg(expr.binary(BinOper::As, Expr::TypeName(r#type.into())))
}

/// Call `COALESCE` function.
Expand Down
4 changes: 4 additions & 0 deletions src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ pub struct DatabaseName(pub DynIden);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SchemaName(pub Option<DatabaseName>, pub DynIden);

/// An SQL type name, potentially qualified as `(database.)(schema.)type`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TypeName(pub Option<SchemaName>, pub DynIden);

/// A table name, potentially qualified as `(database.)(schema.)table`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TableName(pub Option<SchemaName>, pub DynIden);
Expand Down
15 changes: 15 additions & 0 deletions src/types/qualification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ where
}
}

/// Construct a [`TypeName`] from 1-3 parts (`(database?).(schema?).type`)
impl<T> From<T> for TypeName
where
T: MaybeQualifiedTwice,
{
fn from(value: T) -> Self {
let (schema_parts, r#type) = value.into_3_parts();
let schema_name = schema_parts.map(|schema_parts| match schema_parts {
(Some(db), schema) => SchemaName(Some(DatabaseName(db)), schema),
(None, schema) => SchemaName(None, schema),
});
TypeName(schema_name, r#type)
}
}

/// Construct a [`TableName`] from 1-3 parts (`(database?).(schema?).table`)
impl<T> From<T> for TableName
where
Expand Down