While playing with Diesel, I got stuck writing a function which takes an vector of String
s as input and does the following:
- Combine all
String
s to a large query - run the query on the
Connection
- process the result
- return a
Vec
If I construct the query in one step, it works just fine:
fn get_books(authors: Vec<String>, connection: SqliteConnection) {
use schema::ebook::dsl::*;
let inner = author
.like(format!("%{}%", authors[0]))
.and(author.like(format!("%{}%", authors[1])))
.and(author.like(format!("%{}%", authors[2])));
ebook
.filter(inner)
.load::<Ebook>(&connection)
.expect("Error loading ebook");
}
If I try to generate the query in more steps (needed in order to work with the variable length of the input vector) I can't get it to compile:
fn get_books(authors: Vec<String>, connection: SqliteConnection) {
use schema::ebook::dsl::*;
let mut inner = author
.like(format!("%{}%", authors[0]))
.and(author.like(format!("%{}%", authors[1]))); // <1>
inner = inner.and(author.like(format!("%{}%", authors[2]))); // <2>
ebook
.filter(inner)
.load::<Ebook>(&connection)
.expect("Error loading ebook");
}
This generates the following error:
inner = inner.and(author.like(format!("%{}%",authors[2])));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `diesel::expression::operators::Like`, found struct `diesel::expression::operators::And`
I don't understand why Rust expects a Like
and not an And
. The function an the line line marked <1>
returns an And
and therefore an And
is stored in inner
.
What am I missing? Why does the first bit of code compile and the second won't? What is the right way to generate this kind of query?