I am trying to make an Actix API with Diesel, and in making the first endpoint (/books/create), I am having trouble trying to get the inserted value back into my code.
This is my insert:
use diesel::prelude::*;
use crate::models::Book;
use crate::schema::books;
use crate::db;
pub fn create_book(book: &Book) -> Book {
let mut connection: SqliteConnection = db::establish_connection();
let result: QueryResult<Book> = diesel::insert_into(books::table)
.values([book])
.get_result::<Book>(&mut connection);
result.unwrap()
}
This is the error, which I wrapped in a pastebin since it's too long for Stackoverflow: https://pastebin.com/Evq6tUYq
I wonder if it can be a problem of the schema or model, but they seem to be okay'ish and don't have mismatching values, as far as I know:
use diesel::prelude::*;
use serde::{Serialize, Deserialize};
use crate::schema::books;
#[derive(Queryable, Serialize, Deserialize, Insertable)]
#[diesel(table_name = books)]
pub struct Book {
pub id: i32,
pub title: String,
pub author: String,
pub creation_date: Option<String>,
pub publishing_house: Option<String>,
pub release_date: Option<String>,
pub cover_image: Option<String>
}
diesel::table! {
books (id) {
id -> Integer,
title -> Text,
author -> Text,
publishing_house -> Nullable<Text>,
release_date -> Nullable<Text>,
cover_image -> Nullable<Text>,
creation_date -> Nullable<Text>,
}
}
Where is the error? What's missing?
It's impossible to answer this question as it is missing important details like the used diesel version, and the enabled feature flags for diesel.
The underlying problem is that .get_result() uses INSERT INTO … RETURNING SQL statements internally. These are only supported by Sqlite 3.35 or newer. As of this support for such statements is behind a separate diesel feature flag. You need to enable the returning_clauses_for_sqlite_3_35 feature flag.
That by itself will not fix the issue. .values([book]) creates a array with one element and tries to insert that. This will cause diesel to use a batch insert statement, which normally allows to insert more than one element at once. While this is supported for the sqlite backend it cannot be used in combination with the returning support described above, as SQLite is missing another SQL feature here (using the DEFAULT keyword to signal that a certain value should be replaced by the corresponding database default value). In your case this can be fixed by just calling .values(&book), which constructs an ordinary single row insert.
You cant use Queryable and Insertable trait in the same Book struct you must separate them into 2 different structs.
#[derive(Queryable, Serialize, Deserialize)]
pub struct Book {
pub id: i32,
pub title: String,
pub author: String,
pub creation_date: Option<String>,
pub publishing_house: Option<String>,
pub release_date: Option<String>,
pub cover_image: Option<String>
}
#[derive(Insertable)]
#[diesel(table_name = books)]
pub struct BookInsert {
pub id: i32,
pub title: String,
pub author: String,
pub creation_date: Option<String>,
pub publishing_house: Option<String>,
pub release_date: Option<String>,
pub cover_image: Option<String>
}
Related
If I have a struct I need Default implemented on, if all the field's types have Default implemented themsevles, then I can use the derive macro, otherwise I need to implement Default manually. However, there are some situations where I have a large struct where almost all the fields would be derivable, except there is a small number of fields with types which do not have Default implemented, and I can impl myself because the type is external. This ends up with the situation in the below example. I would prefer to avoid this as it means I need to keep the fields in sync between two places, which is more time consuming, error prone, and verbose. I'm hoping there might be some syntactical suagr to avoid this, but I'm new to rust and can't think of any. I'm thinking something like:
impl Default for Data2 {
fn default() -> Self {
Self {
external_data: ExternalType::One,
..Default::default(),
}
}
}
Example
#[derive(Default)]
struct Data {
name: Option<String>,
flag: bool,
selected: Vec<String>,
show_reference: Option<String>,
index: Option<usize>,
create_name: String,
create_type: String,
}
enum ExternalType {
One,
Two,
}
// #[derive(Default)]
struct Data2 {
name: Option<String>,
flag: bool,
selected: Vec<String>,
show_reference: Option<String>,
index: Option<usize>,
create_name: String,
create_type: String,
external_data: ExternalType,
}
impl Default for Data2 {
fn default() -> Self {
Self {
name: Default::default(),
flag: Default::default(),
selected: Default::default(),
show_reference: Default::default(),
index: Default::default(),
create_name: Default::default(),
create_type: Default::default(),
external_data: ExternalType::One,
}
}
}
I think the smart-default crate can handle this. It lets you derive SmartDefault, which derives Default for all fields except those with a #[default(my_default_value)] attribute.
Example:
use smart_default::SmartDefault;
#[derive(SmartDefault)]
enum Foo {
Bar,
#[default]
Baz {
#[default = 12]
a: i32,
b: i32,
#[default(Some(Default::default()))]
c: Option<i32>,
#[default(_code = "vec![1, 2, 3]")]
d: Vec<u32>,
#[default = "four"]
e: String,
},
Qux(i32),
}
There's also the more general derivative crate which lets you customize how all derives work, not just Default, but is a tad more verbose (because it's more general).
Example:
use derivative::Derivative;
#[derive(Derivative)]
#[derivative(Default)]
pub struct RegexOptions {
pub pats: Vec<String>,
#[derivative(Default(value="10 * (1 << 20)"))]
pub size_limit: usize,
#[derivative(Default(value="2 * (1 << 20)"))]
pub dfa_size_limit: usize,
pub case_insensitive: bool,
pub multi_line: bool,
pub dot_matches_new_line: bool,
pub swap_greed: bool,
pub ignore_whitespace: bool,
#[derivative(Default(value="true"))]
pub unicode: bool,
}
As with most Orphan rule problems the only option available is the New Type pattern but I'm not sure this is really an improvement over a manual default impl.
struct ExternalWithDefault(ExternalType);
impl Default for ExternalWithDefault {
fn default() -> Self {
Self(ExternalType::One)
}
}
...
#[derive(Default)]
struct Data2 {
name: Option<String>,
flag: bool,
selected: Vec<String>,
show_reference: Option<String>,
index: Option<usize>,
create_name: String,
create_type: String,
external_data: ExternalWithDefault,
}
I need to serialize some data into files. For the sake of memory efficiency, I want to use the default compact serializer of MessagePack (MsgPack), as it only serializes field values w/o their names. I also want to be able to make changes to the data structure in future versions, which obviously can't be done w/o also storing some meta/versioning information. I imagine the most efficient way to do it is to simply use some "header" field for that purpose. Here is an example:
pub struct Data {
pub version: u8,
pub items: Vec<Item>,
}
pub struct Item {
pub field_a: i32,
pub field_b: String,
pub field_c: i16, // Added in version 3
}
Can I do something like that in rmp-serde (or maybe some other crate?) - to somehow annotate that a certain struct field should only be taken into account for specific file versions?
You can achieve this by writing a custom deserializer like this:
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize};
#[derive(Serialize)]
pub struct Data {
pub version: u8,
pub items: Vec<Item>,
}
#[derive(Serialize)]
pub struct Item {
pub field_a: i32,
pub field_b: String,
pub field_c: i16, // Added in version 3
}
impl<'de> Deserialize<'de> for Data {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
// Inner structs, used for deserializing only
#[derive(Deserialize)]
pub struct InnerData {
version: u8,
items: Vec<InnerItem>,
}
#[derive(Deserialize)]
pub struct InnerItem {
field_a: i32,
field_b: String,
field_c: Option<i16>, // Added in version 3 - note that this field is optional
}
// Deserializer the inner structs
let inner_data = InnerData::deserialize(deserializer)?;
// Get the version so we can add custom logic based on the version later on
let version = inner_data.version;
// Map the InnerData/InnerItem structs to Data/Item using our version based logic
Ok(Data {
version,
items: inner_data
.items
.into_iter()
.map(|item| {
Ok(Item {
field_a: item.field_a,
field_b: item.field_b,
field_c: if version < 3 {
42 // Default value
} else {
// Get the value of field_c
// If it's missing return an error, since it's required since version 3
// Otherwise return the value
item.field_c
.map_or(Err(D::Error::missing_field("field_c")), Ok)?
},
})
})
.collect::<Result<_, _>>()?,
})
}
}
Short explanation how the deserializer works:
We create a "dumb" inner struct which is a copy of your structs but the "new" fields are optional
We deserialize to the new inner structs
We map from our inner to our outer structs using version-based logic
If one of the new fields is missing in a new version we return a D::Error::missing_field error
Using SeaOrm, I want to create a model that has no relations. Essentially, a DB with one table.
This seems like it should be super easy, but the documentation doesn't cover this and the DeriveEntityModel macro requires all the boilerplate for entity relations to be present.
What I want is:
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "device")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(column_name = "uuid")]
pub uuid: Uuid,
#[sea_orm(column_name = "location")]
pub location: Option<String>,
#[sea_orm(column_name = "lastHeard")]
pub lastHeard: Option<DateTime>
}
And the error I get is:
cannot find type `Relation` in this scope
help: you might have meant to use the associated type: `Self::Relation`rustc(E0412)
the trait bound `models::device::ActiveModel: sea_orm::ActiveModelBehavior` is not satisfied
the trait `sea_orm::ActiveModelBehavior` is not implemented for `models::device::ActiveModel`
I'm thinking there must be another macro to use, one that doesn't require relations, but I can't find it in the docs.
thanks for trying SeaORM. Try to define an empty Relation enum like below.
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "device")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(column_name = "uuid")]
pub uuid: Uuid,
#[sea_orm(column_name = "location")]
pub location: Option<String>,
#[sea_orm(column_name = "lastHeard")]
pub lastHeard: Option<DateTime>
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
I have struct from which I want to extract the data.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RunResult {
pub runs: Vec<RunDetails>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RunDetails {
pub details: String,
pub name: String,
pub id: String,
pub type: String,
}
I am getting the data which got inserted in above struct in the variable result which I am iterating below
let my_result:RunResult = result
.runs
.into_iter()
.filter(|line| line.details.contains(&"foo"))
.collect();
I am getting the error as
value of type `RunResult` cannot be built from `std::iter::Iterator<Item=RunDetails>`
I want to get the record where type=OK, details contains foo with highest id.
How can I achieve this?
Check out the documentation for collect here.
Your struct RunResult should implement FromIterator<RunDetails>.
Try adding this (untested by me):
impl FromIterator<RunDetails> for RunResult {
fn from_iter<I: IntoIterator<Item=RunDetails>>(iter: I) -> Self {
Self {
runs: Vec::from_iter(iter);
}
}
}
I am using the Diesel crate to perform some database work. In some tables, two columns of the table should be treated together as a single key.
This pattern is repeated in many places in the database, so it would be nice to avoid a heap of repeated copy-paste code to handle this. However, I can't convince Diesel to automatically produce a type I can use in queries or inserts.
Consider the table
table! {
records (iid) {
iid -> Integer,
id_0 -> BigInt,
id_1 -> BigInt,
data -> Text,
}
}
and the ideal types
#[derive(Debug, Copy, Clone, FromSqlRow)]
pub struct RecordId {
id_0: i64,
id_1: i64,
}
#[derive(Queryable, Debug)]
pub struct Record {
pub iid: i32,
pub id: RecordId,
pub data: String,
}
This code compiles OK, but when I try to use it I get an error, for example:
pub fn find(connection: &SqliteConnection) -> types::Record {
records
.find(1)
.get_result::<types::Record>(connection)
.unwrap()
}
produces:
error[E0277]: the trait bound `(i32, types::RecordId, std::string::String): diesel::Queryable<(diesel::sql_types::Integer, diesel::sql_types::BigInt, diesel::sql_types::BigInt, diesel::sql_types::Text), _>` is not satisfied
--> src/main.rs:76:21
|
76 | records.find(1).get_result::<types::Record>(connection).unwrap()
| ^^^^^^^^^^ the trait `diesel::Queryable<(diesel::sql_types::Integer, diesel::sql_types::BigInt, diesel::sql_types::BigInt, diesel::sql_types::Text), _>` is not implemented for `(i32, types::RecordId, std::string::String)`
|
= help: the following implementations were found:
<(A, B, C) as diesel::Queryable<(SA, SB, SC), __DB>>
<(A, B, C) as diesel::Queryable<diesel::sql_types::Record<(SA, SB, SC)>, diesel::pg::Pg>>
= note: required because of the requirements on the impl of `diesel::Queryable<(diesel::sql_types::Integer, diesel::sql_types::BigInt, diesel::sql_types::BigInt, diesel::sql_types::Text), _>` for `types::Record`
= note: required because of the requirements on the impl of `diesel::query_dsl::LoadQuery<_, types::Record>` for `diesel::query_builder::SelectStatement<types::records::table, diesel::query_builder::select_clause::DefaultSelectClause, diesel::query_builder::distinct_clause::NoDistinctClause, diesel::query_builder::where_clause::WhereClause<diesel::expression::operators::Eq<types::records::columns::iid, diesel::expression::bound::Bound<diesel::sql_types::Integer, i32>>>>`
If I create a version which does not contain the RecordId but has the sub-pieces directly, then there is no error:
pub struct RecordDirect {
pub iid: i32,
pub id_0: i64,
pub id_1: i64,
pub data: String,
}
// ...
pub fn find_direct(connection: &SqliteConnection) -> types::RecordDirect {
records
.find(1)
.get_result::<types::RecordDirect>(connection)
.unwrap()
}
Similarly, I can manually implement the Queryable trait and that works OK too,
#[derive(Debug)]
pub struct RecordManual {
pub iid: i32,
pub id: RecordId,
pub data: String,
}
impl Queryable<records::SqlType, diesel::sqlite::Sqlite> for RecordManual {
type Row = (i32, i64, i64, String);
fn build(row: Self::Row) -> Self {
RecordManual {
iid: row.0,
id: RecordId {
id_0: row.1,
id_1: row.2,
},
data: row.3,
}
}
}
// ...
pub fn find_manual(connection: &SqliteConnection) -> types::RecordManual {
records
.find(1)
.get_result::<types::RecordManual>(connection)
.unwrap()
}
This case is ugly to maintain and I could not work out how to get it working for insertion — manually implementing Insertable seems a little trickier than Queryable.
To make this easier for anyone looking at it to play with, I've created a repository containing an almost compiling small reproducer containing the code blocks from this post. (Normally I'd put it up on the rust-playground, but that doesn't support diesel). You can find that code at https://github.com/mikeando/diesel_custom_type_demo.
Is there a way to make the #[derive(Queryable)] (and #[derive(Insertable)]) work for these kinds of cases?
A minimal reproducer for the failing initial case is:
#[macro_use]
extern crate diesel;
use diesel::prelude::*;
mod types {
use diesel::deserialize::Queryable;
use diesel::sqlite::SqliteConnection;
table! {
records (iid) {
iid -> Integer,
id_0 -> BigInt,
id_1 -> BigInt,
data -> Text,
}
}
#[derive(Debug, Copy, Clone, FromSqlRow)]
pub struct RecordId {
id_0: i64,
id_1: i64,
}
// Using a RecordId in a Record compiles, but
// produces an error when used in an actual query
#[derive(Queryable, Debug)]
pub struct Record {
pub iid: i32,
pub id: RecordId,
pub data: String,
}
}
use types::records::dsl::*;
pub fn find(connection:&SqliteConnection) -> types::Record {
records.find(1).get_result::<types::Record>(connection).unwrap()
}
Is there a way to make the #[derive(Queryable)] (and #[derive(Insertable)]) work for these kinds of cases?
For #[derive(Insertable)] this is simply possible by adding a #[diesel(embedded)] to your id field and a #[derive(Insertable)] on both structs. See the documentation of Insertable for details.
For #[derive(Queryable)] this is not possible because Queryable is supposed to be a plain mapping from query result to struct, with the basic assumption that the "shape" of the output remains the same (at least for the derive).