Getting the following error:
error[E0308]: mismatched types
--> src/u/r/api/products/articles.rs:17:69
|
17 | let query = web::block(move || articles::table.load::<Articles>(&*connection).unwrap()).await;
| ---------------- ^^^^^^^^^^^^ types differ in mutability
| |
| arguments to this function are incorrect
|
= note: expected mutable reference `&mut _`
found reference `&PgConnection`
note: associated function defined here
--> /Users/b/.cargo/registry/src/github.com/diesel-2.0.2/src/query_dsl/mod.rs:1497:8
|
1497 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
| ^^^^
I am using Diesel v2, it worked before I upgraded to the latest version.
What am I doing wrong?
use crate::u::db::connection::DbPool;
use actix_web::{get, web, HttpResponse, Responder};
#[get("/product/articles")]
pub async fn list(db_pool: web::Data<DbPool>) -> impl Responder {
use crate::u::db::models::products::Articles;
use crate::u::db::schemas::products::articles;
let connection = db_pool.get();
if let Err(e) = connection {
return HttpResponse::InternalServerError().body(format!("E1-{:?}", e));
}
let connection = connection.unwrap();
let query = web::block(move || articles::table.load::<Articles>(&*connection).unwrap()).await;
if let Err(e) = query {
return HttpResponse::InternalServerError().body(format!("E2-{:?}", e));
}
let q = query.expect("oops not Ok");
HttpResponse::Ok().json(q)
}
models/products.rs
use chrono::{DateTime, Utc};
use uuid::Uuid;
use crate::u::db::schemas::products::*;
#[derive(Queryable, Debug, Identifiable, serde::Serialize, serde::Deserialize)]
#[table_name = "articles"]
#[primary_key(prod_art_pvt_uuid)]
pub struct Articles {
pub prod_art_pvt_uuid: Uuid,
pub prod_art_pub_uuid: Uuid,
pub prod_article_pub_id: i32,
pub t: DateTime<Utc>,
}
db/connection.rs
use crate::u::config;
use diesel::pg::PgConnection;
use diesel::r2d2::ConnectionManager;
use r2d2::Pool;
pub type DbPool = r2d2::Pool<ConnectionManager<PgConnection>>;
pub fn get_pool() -> DbPool {
let url: String = config::get("database_url");
println!("Connecting to database...");
let manager = ConnectionManager::<PgConnection>::new(url);
Pool::builder()
.build(manager)
.expect("Failed to create database connection pool.")
}
The error message already indicates what needs to be change. The important part is that one:
error[E0308]: mismatched types
--> src/u/r/api/products/articles.rs:17:69
|
17 | let query = web::block(move || articles::table.load::<Articles>(&*connection).unwrap()).await;
| ---------------- ^^^^^^^^^^^^ types differ in mutability
| |
| arguments to this function are incorrect
|
= note: expected mutable reference `&mut _`
found reference `&PgConnection`
As you can see there you need to change the argument of the load function to a mutable reference. You try to pass an immutable reference, which is something that's not accepted by the underlying function.
I recommend to checkout the Diesel Migration guide which contains an overview of most user-facing breaking changes of the 2.0 release.
Related
I want to create a rest api with rust and can't make it work.
My relevant code so far:
In the main.rs:
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// Loading .env into environment variable.
dotenv::dotenv().ok();
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
// set up database connection pool
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL");
let manager = ConnectionManager::<PgConnection>::new(database_url);
let pool: DbPool = r2d2::Pool::builder()
.test_on_check_out(true)
.build(manager)
.expect("Could not build connection pool");
let port = std::env::var("PORT").expect("$PORT is not set.");
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.wrap(middleware::Logger::default())
.route("/", web::get().to(|| async { "Actix REST API" }))
.service(handlers::common::houses::index)
})
.bind(("0.0.0.0", port.parse().unwrap()))?
.run()
.await
}
The schema:
diesel::table! {
houses (id) {
id -> Int4,
user_id -> Varchar,
street -> Varchar,
figure -> Varchar,
floor -> Varchar,
create_date -> Timestamp,
update_date -> Timestamp,
is_deleted -> Bool,
}
}
The model:
#[derive(Debug, Serialize, Deserialize, Queryable)]
pub struct House {
pub id: i32,
pub user_id: String,
pub street: String,
pub figure: String,
pub floor: String,
pub create_date: chrono::NaiveDateTime,
pub update_date: chrono::NaiveDateTime,
pub is_deleted: bool,
}
The handler:
#[get("/houses")]
async fn index(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> {
let houses = web::block(move || {
let conn = &pool.get()?;
find_all(&conn)
})
.await?
.map_err(actix_web::error::ErrorInternalServerError)?;
Ok(HttpResponse::Ok().json(houses))
}
fn find_all(conn: &PgConnection) -> Result<Vec<House>, DbError> {
use crate::schemas::common::houses::houses::dsl::*;
let items =houses.load::<House>(&mut conn)?;
Ok(items)
}
The dependencies are:
[dependencies]
actix-web = "4"
chrono = { version = "0.4.19", features = ["serde"] }
diesel = { version = "2.0.3", features = ["postgres", "r2d2", "chrono"] }
dotenv = "0.15.0"
env_logger = "0.10.0"
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0"`
It keeps giving an error, and I don't understand why.
The error is:
`error[E0277]: the trait bound `&diesel::PgConnection: LoadConnection` is not satisfied src\handlers\common\houses.rs:25:37
| 25 | let items =houses.load::<House>(&mut conn)?;
| ---- -^^^^^^^^
| | | the trait `LoadConnection` is not implemented for `&diesel::PgConnection` help: consider removing the leading `&`-reference required by a bound introduced by this call
| note: required for `table` to implement `LoadQuery<'_, &diesel::PgConnection, House>` note: required by a bound in `diesel::RunQueryDsl::load`
I've seen a similar error with the diesel version 1.4, but I think that this version is different.
Plus I'm starting with rust and I'm a little lost in general at the moment.
I was hopping someone knows what the problem is and how to fix it.
PgConnection implements LoadConnection but &PgConnection does not (note the extra &).
Make conn mutable and pass as a mutable reference:
#[get("/houses")]
async fn index(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> {
let houses = web::block(move || {
let mut conn = pool.get()?; // <------------
find_all(&mut conn) // <------------
})
.await?
.map_err(actix_web::error::ErrorInternalServerError)?;
Ok(HttpResponse::Ok().json(houses))
}
fn find_all(conn: &mut PgConnection) -> Result<Vec<House>, DbError> {
// ^^^ <------------
use crate::schemas::common::houses::houses::dsl::*;
let items = houses.load::<House>(conn)?; // <------------
Ok(items)
}
I'm triying to do an Api REST with rust and postres but I cant make it work because the relation between these two.
The actual problem is that I have a column in postgres as jsonb and when I return the data and try to save it in a struct always gives error. Same problem when I try to save the data.
This are the models.(The option is only because I'm testing thing, it should return a value)
#[derive(Debug, Serialize, Deserialize)]
pub struct CategoryView {
pub id: i32,
pub category_name: String,
pub category_custom_fields: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct CategoryPayload {
pub category_name: String,
pub category_custom_fields: Option<serde_json::Value>,
}
This are the postgres queries:
fn find_all(conn: &mut DbPooled) -> Result<Vec<CategoryView>, DbError> {
let mut query = "SELECT id, category_name, category_custom_fields FROM accounting.categories".to_owned();
query.push_str(" WHERE user_id = $1");
query.push_str(" AND is_deleted = false");
let items = conn.query(&query, &[&unsafe { CURRENT_USER.to_owned() }])?;
let items_view: Vec<CategoryView> = items
.iter()
.map(|h| CategoryView {
id: h.get("id"),
category_name: h.get("category_name"),
category_custom_fields: h.get("category_custom_fields"),
})
.collect();
Ok(items_view)
}
fn add(payload: &CategoryPayload, conn: &mut DbPooled) -> Result<CategoryView, DbError> {
let mut query =
"INSERT INTO accounting.categories (user_id, category_name, category_custom_fields, create_date, update_date)"
.to_owned();
query.push_str(" VALUES ($1, $2, $3, now(), now())");
query.push_str(" RETURNING id");
let item_id = conn
.query_one(
&query,
&[
&unsafe { CURRENT_USER.to_owned() },
&payload.category_name,
&payload.category_custom_fields,
],
)?
.get(0);
let inserted_item = CategoryView {
id: item_id,
category_name: payload.category_name.to_string(),
category_custom_fields: payload.category_custom_fields,
};
Ok(inserted_item)
}
with update happens to but I think is the same solution that the one form the add function.
The error is:
the trait bound `serde_json::Value: ToSql` is not satisfied
the following other types implement trait `ToSql`:
&'a T
&'a [T]
&'a [u8]
&'a str
Box<[T]>
Box<str>
Cow<'a, str>
HashMap<std::string::String, std::option::Option<std::string::String>, H>
and 17 others
required for `std::option::Option<serde_json::Value>` to implement `ToSql`
required for the cast from `std::option::Option<serde_json::Value>` to the object type `dyn ToSql + Sync`rustcClick for full compiler diagnostic`
For what I read serde_json::Value is the equivalent to jsonb so I don't understand it.
I had a similar problem previously trying to work with a decimal value in postgres, I had to change it to integer and save the value multiplied in the database. Is a money column so maybe if you help me with that too I will change it back.
I was hopping some could explain to me how to fix it and why this happens so I can avoid have to ask for help with the datatypes in the future.
The problem was in the depencies.
It looks like some dependencies have features that add aditional functionablility.
I had installed the dependencie without any feature so when I added the features it started to work without issues.
Only had to change from:
[dependencies]
postgres = "0.19.4"
to:
[dependencies]
postgres = { version = "0.19.4", features = ["with-chrono-0_4", "with-serde_json-1"] }
Chrono for dates and serde_json for jsonb.
I'll check the decimal problem but I think will be the same solution.
I am a beginner in rust.
I know what happened, spend a whole afternoon to try, and finally, could not find any solution...
Need help from kind people T_T
use kafka::client::{FetchOffset, GroupOffsetStorage, KafkaClient};
fn main() {
let mut client = KafkaClient::new(vec!["localhost:9092".to_owned()]);
client.load_metadata_all().unwrap();
client.set_group_offset_storage(GroupOffsetStorage::Kafka);
for topic in client.topics().names() {
let topic_offsets = client.fetch_topic_offsets(topic, FetchOffset::Latest).unwrap();
println!("{:?}", topic_offsets);
let group_topic_offsets = client.fetch_group_topic_offsets("test", topic).unwrap();
println!("{:?}", group_topic_offsets);
for (partition_index, tp_offset) in topic_offsets.iter().enumerate() {
println!("partition {}'s lag = {}", partition_index, tp_offset.offset - group_topic_offsets[partition_index].offset)
}
}
}
error[E0502]: cannot borrow `client` as mutable because it is also borrowed as immutable
--> src/main.rs:11:31
|
7 | for topic in &mut client.topics().names() {
| ----------------------------
| | |
| | immutable borrow occurs here
| immutable borrow later used here
...
11 | let group_topic_offsets = client.fetch_group_topic_offsets("test", topic).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
error: aborting due to 2 previous errors
I am using r2d2_postgres to run raw SQL and return the result directly in Actix response.
I need to run raw sql with dynamic data, types and unknown at compile time columns/data types etc. To do this, I came across serde_json::value::RawValue:
It states: "A RawValue can be used to defer parsing parts of a payload until later, or to avoid parsing it at all in the case that part of the payload just needs to be transferred verbatim into a different output object."
https://docs.serde.rs/serde_json/value/struct.RawValue.html
I basically want to avoid parsing it at all and just send it to the Actix client.
Here's my code:
let mut conn = pool.get().expect("Couldn't get db connection from pool");
let result = web::block(move || conn.query("select jsonb_agg(t) from (select * from useraccountview) t",&[]))
.await;
match result {
Ok(result) => {
let foo : serde_json::value::RawValue = result[0].get(0);
HttpResponse::Ok().content_type("application/json").json(foo)
},
Err(e) => HttpResponse::NotAcceptable().body(e.to_string())
}
This gives me 2 errors:
error[E0277]: the trait bound `serde_json::value::RawValue: FromSql<'_>` is not satisfied
--> src/main.rs:188:63
|
188 | let foo : serde_json::value::RawValue = result[0].get(0);
| ^^^ the trait `FromSql<'_>` is not implemented for `serde_json::value::RawValue`
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> src/main.rs:188:17
|
188 | let foo : serde_json::value::RawValue = result[0].get(0);
| ^^^ doesn't have a size known at compile-time
I am very new to Rust so I am probably missing some concept on how to fix this.
Why doesn't this Rust code compile?
use std::fs;
use std::io;
use std::path::Path;
fn do_job(path: &Path) -> io::Result<()> {
let mut files: Vec<&Path> = Vec::new();
for entry in try!(fs::read_dir(path)) {
entry = try!(entry);
}
}
it's very similar to code in the docs.
compile error:
<std macros>:3:43: 3:46 error: mismatched types:
expected `core::result::Result<std::fs::DirEntry, std::io::error::Error>`,
found `std::fs::DirEntry`
(expected enum `core::result::Result`,
found struct `std::fs::DirEntry`) [E0308]
<std macros>:3 $ crate:: result:: Result:: Ok ( val ) => val , $ crate:: result:: Result::
^~~
src/main.rs:13:17: 13:28 note: in this expansion of try! (defined in <std macros>)
<std macros>:3:43: 3:46 help: run `rustc --explain E0308` to see a detailed explanation
src/main.rs:12:5: 14:6 error: mismatched types:
expected `core::result::Result<(), std::io::error::Error>`,
found `()`
(expected enum `core::result::Result`,
found ()) [E0308]
src/main.rs:12 for entry in try!(fs::read_dir(path)) {
src/main.rs:13 entry = try!(entry);
src/main.rs:14 }
src/main.rs:12:5: 14:6 help: run `rustc --explain E0308` to see a detailed explanation
It looks like you want a new binding for each directory entry in your loop:
for entry in fs::read_dir(path)? {
let entry = entry?;
}
this new binding will shadow the one introduced in the for expression.
The type of entry introduced by the loop is Result<DirEntry> which you are trying to unwrap using ? (formerly try!). However you are attempting to assign the resulting DirEntry to a binding with type Result<DirEntry>, hence the error.
The second error indicates that the return value from your function does not match the declared type of io::Result<()>. You can simply return Ok(()):
fn do_job(path: &Path) -> io::Result<()> {
let mut files: Vec<&Path> = Vec::new();
for entry in fs::read_dir(path)? {
let entry = entry?;
//process entry
}
Ok(())
}