diesel/expression_methods/text_expression_methods.rs
1use expression::operators::{Concat, Like, NotLike};
2use expression::{AsExpression, Expression};
3use sql_types::{Nullable, Text};
4
5/// Methods present on text expressions
6pub trait TextExpressionMethods: Expression + Sized {
7 /// Concatenates two strings using the `||` operator.
8 ///
9 /// # Example
10 ///
11 /// ```rust
12 /// # #[macro_use] extern crate diesel;
13 /// # include!("../doctest_setup.rs");
14 /// #
15 /// # table! {
16 /// # users {
17 /// # id -> Integer,
18 /// # name -> VarChar,
19 /// # hair_color -> Nullable<Text>,
20 /// # }
21 /// # }
22 /// #
23 /// # fn main() {
24 /// # use self::users::dsl::*;
25 /// # use diesel::insert_into;
26 /// #
27 /// # let connection = connection_no_data();
28 /// # connection.execute("CREATE TABLE users (
29 /// # id INTEGER PRIMARY KEY,
30 /// # name VARCHAR(255) NOT NULL,
31 /// # hair_color VARCHAR(255)
32 /// # )").unwrap();
33 /// #
34 /// # insert_into(users)
35 /// # .values(&vec![
36 /// # (id.eq(1), name.eq("Sean"), hair_color.eq(Some("Green"))),
37 /// # (id.eq(2), name.eq("Tess"), hair_color.eq(None)),
38 /// # ])
39 /// # .execute(&connection)
40 /// # .unwrap();
41 /// #
42 /// let names = users.select(name.concat(" the Greatest")).load(&connection);
43 /// let expected_names = vec![
44 /// "Sean the Greatest".to_string(),
45 /// "Tess the Greatest".to_string(),
46 /// ];
47 /// assert_eq!(Ok(expected_names), names);
48 ///
49 /// // If the value is nullable, the output will be nullable
50 /// let names = users.select(hair_color.concat("ish")).load(&connection);
51 /// let expected_names = vec![
52 /// Some("Greenish".to_string()),
53 /// None,
54 /// ];
55 /// assert_eq!(Ok(expected_names), names);
56 /// # }
57 /// ```
58 fn concat<T: AsExpression<Self::SqlType>>(self, other: T) -> Concat<Self, T::Expression> {
59 Concat::new(self, other.as_expression())
60 }
61
62 /// Returns a SQL `LIKE` expression
63 ///
64 /// This method is case insensitive for SQLite and MySQL.
65 /// On PostgreSQL, `LIKE` is case sensitive. You may use
66 /// [`ilike()`](../expression_methods/trait.PgTextExpressionMethods.html#method.ilike)
67 /// for case insensitive comparison on PostgreSQL.
68 ///
69 /// # Examples
70 ///
71 /// ```rust
72 /// # #[macro_use] extern crate diesel;
73 /// # include!("../doctest_setup.rs");
74 /// #
75 /// # fn main() {
76 /// # run_test().unwrap();
77 /// # }
78 /// #
79 /// # fn run_test() -> QueryResult<()> {
80 /// # use schema::users::dsl::*;
81 /// # let connection = establish_connection();
82 /// #
83 /// let starts_with_s = users
84 /// .select(name)
85 /// .filter(name.like("S%"))
86 /// .load::<String>(&connection)?;
87 /// assert_eq!(vec!["Sean"], starts_with_s);
88 /// # Ok(())
89 /// # }
90 /// ```
91 fn like<T: AsExpression<Self::SqlType>>(self, other: T) -> Like<Self, T::Expression> {
92 Like::new(self.as_expression(), other.as_expression())
93 }
94
95 /// Returns a SQL `NOT LIKE` expression
96 ///
97 /// This method is case insensitive for SQLite and MySQL.
98 /// On PostgreSQL `NOT LIKE` is case sensitive. You may use
99 /// [`not_ilike()`](../expression_methods/trait.PgTextExpressionMethods.html#method.not_ilike)
100 /// for case insensitive comparison on PostgreSQL.
101 ///
102 /// # Examples
103 ///
104 /// ```rust
105 /// # #[macro_use] extern crate diesel;
106 /// # include!("../doctest_setup.rs");
107 /// #
108 /// # fn main() {
109 /// # run_test().unwrap();
110 /// # }
111 /// #
112 /// # fn run_test() -> QueryResult<()> {
113 /// # use schema::users::dsl::*;
114 /// # let connection = establish_connection();
115 /// #
116 /// let doesnt_start_with_s = users
117 /// .select(name)
118 /// .filter(name.not_like("S%"))
119 /// .load::<String>(&connection)?;
120 /// assert_eq!(vec!["Tess"], doesnt_start_with_s);
121 /// # Ok(())
122 /// # }
123 /// ```
124 fn not_like<T: AsExpression<Self::SqlType>>(self, other: T) -> NotLike<Self, T::Expression> {
125 NotLike::new(self.as_expression(), other.as_expression())
126 }
127}
128
129#[doc(hidden)]
130/// Marker trait used to implement `TextExpressionMethods` on the appropriate
131/// types. Once coherence takes associated types into account, we can remove
132/// this trait.
133pub trait TextOrNullableText {}
134
135impl TextOrNullableText for Text {}
136impl TextOrNullableText for Nullable<Text> {}
137
138impl<T> TextExpressionMethods for T
139where
140 T: Expression,
141 T::SqlType: TextOrNullableText,
142{
143}