I want do using rust diesel filter method to add a filter condition like this:
#[macro_use]
extern crate diesel;
use crate::schema::dict::id;
mod schema;
mod models;
fn main() {
use crate::diesel::prelude::*;
use crate::schema::dict;
let query = dict.filter(id.gt(0));
}
and this is the dict table scheme define:
table! {
dict (id) {
word -> Varchar,
phonetic -> Varchar,
definition -> Varchar,
translation -> Varchar,
pos -> Varchar,
collins -> Nullable<Int4>,
oxford -> Nullable<Int4>,
tag -> Varchar,
bnc -> Int4,
frq -> Int4,
exchange -> Varchar,
detail -> Varchar,
audio -> Varchar,
id -> Int8,
}
}
this is the model define:
use rocket::serde::Serialize;
use rocket::serde::Deserialize;
use crate::schema::dict;
#[derive(Insertable, Serialize, Queryable, Deserialize,Default)]
#[table_name = "dict"]
pub struct QueryEdict {
pub id: i64,
pub word: String,
pub phonetic: String,
pub definition: String,
pub translation: String,
pub pos: String,
pub collins: Option<i32>,
pub oxford: Option<i32>,
pub tag: String,
pub bnc: i32,
pub frq: i32,
pub exchange: String,
pub detail: String,
pub audio: String,
}
show error when compile the rust code:
Compiling rust-learn v0.1.0 (/Users/xiaoqiangjiang/source/reddwarf/backend/rust-learn)
error[E0423]: expected value, found module `dict`
--> src/main.rs:11:17
|
11 | let query = dict.filter(id.gt(0));
| ^^^^-------
| |
| help: use the path separator to refer to an item: `dict::filter`
|
note: unit struct `crate::models::dict::dsl::dict` exists but is inaccessible
--> src/schema.rs:1:1
|
1 | / table! {
2 | | dict (id) {
3 | | word -> Varchar,
4 | | phonetic -> Varchar,
... |
17 | | }
18 | | }
| |_^ not accessible
= note: this error originates in the macro `__diesel_table_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0423`.
error: could not compile `rust-learn` due to previous error
why could not using the diesel filter? what should I do to fix it? This is the Cargo.toml define:
[package]
name = "rust-learn"
version = "0.1.0"
edition = "2018"
[dependencies]
rocket = { version = "0.5.0-rc.1", features = ["json"] }
serde = { version = "1.0.64", features = ["derive"] }
serde_json = "1.0.64"
serde_derive = "1.0"
# database
diesel = { version = "1.4.7", features = ["postgres"] }
this is the system info:
rustc 1.57.0 (f1edd0429 2021-11-29)
diesel = { version = "1.4.7", features = ["postgres","64-column-tables","chrono"] }
Operation System: macOS Monterey 12.3
Databse: PostgreSQL 13
Your error message clearly show the problem:
Compiling rust-learn v0.1.0 (/Users/xiaoqiangjiang/source/reddwarf/backend/rust-learn)
error[E0423]: expected value, found module `dict`
--> src/main.rs:11:17
|
11 | let query = dict.filter(id.gt(0));
| ^^^^-------
| |
| help: use the path separator to refer to an item: `dict::filter`
|
note: unit struct `crate::models::dict::dsl::dict` exists but is inaccessible
--> src/schema.rs:1:1
|
1 | / table! {
2 | | dict (id) {
3 | | word -> Varchar,
4 | | phonetic -> Varchar,
... |
17 | | }
18 | | }
| |_^ not accessible
= note: this error originates in the macro `__diesel_table_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0423`.
error: could not compile `rust-learn` due to previous error
It states that there is no value dict in scope, only a module with that name. A module is not valid in value position. Additionally it gives you a hint how to fix that:
note: unit struct `crate::models::dict::dsl::dict` exists but is inaccessible
This gives you the hint that there is a unit struct with the same name available, but it is not imported. Importing this type does fix your problem.
To give a bit more context: Unit structs are type definitions + value in one. So for
struct UnitStruct;
the identifier UnitStruct can be used in value and in type position. Diesel uses unit structs as identifier for table and column names. Checkout the "Schema in depth" guide for details.
Related
I unfortunately must use sql_query(). However, I'm wondering if there is a way to serialize the database results into a nested struct. I'd like to avoid creating a flattened data type to receive the results from the data and instead use the data struct with nested struct definitions, similar to deserializing json with #[serde(flatten)]
I've attempted this with the following code:
use diesel::*;
use serde::Deserialize;
use diesel::r2d2::{ConnectionManager, PooledConnection};
type DB = diesel::pg::Pg;
type DbConn = PooledConnection<ConnectionManager<PgConnection>>;
diesel::table! {
foo (id) {
id -> Int4,
}
}
diesel::table! {
bar (id) {
id -> Int4,
foo_id -> Int4,
}
}
#[derive(Deserialize, Queryable)]
#[diesel(table_name=foo)]
pub struct Foo {
pub id: i32,
}
#[derive(Deserialize, Queryable, QueryableByName)]
pub struct Nested {
#[sql_type = "Integer"]
pub bar_id: i32,
pub foo: Foo
}
pub fn get_nested(conn: & mut DbConn) {
sql_query("select * from bar join foo on foo.id = bar.foo_id")
.get_results::<Nested>(conn);
}
But it complains
error: Cannot determine the SQL type of foo
--> src/main.rs:30:9
|
30 | pub foo: Foo
| ^^^
|
= help: Your struct must either be annotated with `#[diesel(table_name = foo)]` or have this field annotated with `#[diesel(sql_type = ...)]`
error[E0277]: the trait bound `Untyped: load_dsl::private::CompatibleType<Nested, Pg>` is not satisfied
--> src/main.rs:35:32
|
35 | .get_results::<Nested>(conn);
| ----------- ^^^^ the trait `load_dsl::private::CompatibleType<Nested, Pg>` is not implemented for `Untyped`
| |
| required by a bound introduced by this call
|
= help: the trait `load_dsl::private::CompatibleType<U, DB>` is implemented for `Untyped`
= note: required for `SqlQuery` to implement `LoadQuery<'_, _, Nested>`
note: required by a bound in `get_results`
--> /home/rogers/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.3/src/query_dsl/mod.rs:1695:15
|
1695 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_results`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `rust_test` due to 2 previous errors
[Finished running. Exit status: 101]
Is there a way to serialize the database values into a nested structs when doing raw sql queries in diesel?
To cite from the relevant documentation:
If a field is another struct which implements QueryableByName, instead of a column, you can annotate that struct with #[diesel(embed)]. Then all fields contained by that inner struct are loaded into the embedded struct.
That means that:
Your struct Foo needs to derive QueryableByName as well
The field foo of the Nested struct needs to be annotated with #[diesel(embed)]
I am trying to using rust diesel full text search, first I added the dependencies:
diesel_full_text_search = "1.0.1"
then tweak my search code like this:
#[macro_use]
extern crate diesel;
use diesel::{QueryDsl, RunQueryDsl};
use diesel_full_text_search::{ to_tsvector};
use rust_wheel::config::db::config;
use diesel_full_text_search::TsVectorExtensions;
use crate::model::diesel::dict::dict_models::Article;
mod model;
fn main() {
use model::diesel::dict::dict_schema::article as article_table;
let connection = config::establish_connection();
let mut query = article_table::table.into_boxed::<diesel::pg::Pg>();
let tsvector = to_tsvector("'dolphinzhcfg', title");
query = query.filter(&tsvector.matches("经济".parse().unwrap()));
let query_result = query.load::<Article>(&connection);
}
when I compile this code, shows error like this:
error[E0284]: type annotations needed
--> src/main.rs:17:36
|
17 | query = query.filter(&tsvector.matches("经济".parse().unwrap()));
| ^^^^^^^ cannot infer type for type parameter `T` declared on the associated function `matches`
|
= note: cannot satisfy `<_ as AsExpression<TsQuery>>::Expression == _`
help: consider specifying the type argument in the method call
|
17 | query = query.filter(&tsvector.matches("经济".parse::<F>().unwrap()));
| +++++
For more information about this error, try `rustc --explain E0284`.
error: could not compile `rust-learn` due to previous error
what should I do to avoid this problem? BTW, this is the dict_schema.rs:
table! {
article (id) {
id -> Int8,
user_id -> Int8,
title -> Varchar,
author -> Varchar,
guid -> Varchar,
created_time -> Int8,
updated_time -> Int8,
link -> Nullable<Varchar>,
sub_source_id -> Int8,
cover_image -> Nullable<Varchar>,
channel_reputation -> Int4,
editor_pick -> Nullable<Int4>,
}
}
and this is the dict_models.rs:
// Generated by diesel_ext
#![allow(unused)]
#![allow(clippy::all)]
use std::io::Write;
use diesel::deserialize::FromSql;
use diesel::pg::Pg;
use diesel::serialize::{Output, ToSql};
use diesel::sql_types::Jsonb;
use rocket::serde::Serialize;
use serde::Deserialize;
use chrono::DateTime;
use chrono::Utc;
use crate::model::diesel::dict::dict_schema::*;
#[derive(Queryable,QueryableByName,Debug,Serialize,Deserialize,Default,Clone)]
#[table_name = "article"]
pub struct Article {
pub id: i64,
pub user_id: i64,
pub title: String,
pub author: String,
pub guid: String,
pub created_time: i64,
pub updated_time: i64,
pub link: Option<String>,
pub sub_source_id: i64,
pub cover_image: Option<String>,
pub channel_reputation: i32,
pub editor_pick: Option<i32>,
}
this is the dependencies of the demo:
[package]
name = "rust-learn"
version = "0.1.0"
edition = "2018"
[dependencies]
rocket = { version = "=0.5.0-rc.2", features = ["json"] }
serde = { version = "1.0.64", features = ["derive"] }
serde_json = "1.0.64"
serde_derive = "1.0"
# database
diesel = { version = "1.4.7", features = ["postgres","serde_json"] }
dotenv = "0.15.0"
jsonwebtoken = "7"
chrono = "0.4"
config = "0.11"
ring = "0.16.20"
md5 = "0.7.0"
data-encoding = "2.3.2"
bigdecimal = "0.3.0"
# reddwarf public component
rust_wheel = { git = "https://github.com/jiangxiaoqiang/rust_wheel.git" }
diesel_full_text_search = "1.0.1"
The error message already contains all information required to fix this problem:
= note: cannot satisfy `<_ as AsExpression<TsQuery>>::Expression == _`
help: consider specifying the type argument in the method call
|
17 | query = query.filter(&tsvector.matches("经济".parse::<F>().unwrap()));
| +++++
which means you need to specify whatever type .parse() should parse into, as rustc cannot infer a type there. The concrete type depends on whatever type is expected by matches (checkout the documentation for that).
I am using rust diesel diesel = { version = "1.4.8", features = ["postgres","64-column-tables","chrono","serde_json"] } to do the group by query follow the docs like this:
fpub fn get_bill_book_account_sum(){
use crate::diesel::GroupByDsl;
use diesel::dsl::max;
use crate::model::diesel::dict::dict_schema::test as bill_record_table;
let source_query = bill_record_table::table
.group_by(bill_record_table::id)
.select((max(bill_record_table::tags),bill_record_table::id))
.filter(bill_record_table::dsl::tags.eq(9));
}
then compile this code, shows error like this:
error[E0277]: the trait bound `aggregate_ordering::max::max<BigInt, columns::tags>: NonAggregate` is not satisfied
--> src/main.rs:19:17
|
19 | .select((max(bill_record_table::tags),bill_record_table::id))
| ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonAggregate` is not implemented for `aggregate_ordering::max::max<BigInt, columns::tags>`
| |
| required by a bound introduced by this call
|
= note: required because of the requirements on the impl of `diesel::Expression` for `(aggregate_ordering::max::max<BigInt, columns::tags>, columns::id)`
note: required by a bound in `diesel::QueryDsl::select`
--> /Users/xiaoqiangjiang/.cargo/registry/src/mirrors.tuna.tsinghua.edu.cn-df7c3c540f42cdbd/diesel-1.4.8/src/query_dsl/mod.rs:291:20
|
291 | Selection: Expression,
| ^^^^^^^^^^ required by this bound in `diesel::QueryDsl::select`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `rust-learn` due to previous error
where am I doing wrong? what should I do to fixed this problem? this is the schema define(I have removed all the columns just using 2 columns to make a minimal reproduce example):
table! {
test (id) {
id -> Int8,
tags -> Int8,
}
}
and this is the model define:
// Generated by diesel_ext
#![allow(unused)]
#![allow(clippy::all)]
use std::io::Write;
use diesel::deserialize::FromSql;
use diesel::pg::Pg;
use diesel::serialize::{Output, ToSql};
use diesel::sql_types::Jsonb;
use rocket::serde::Serialize;
use serde::Deserialize;
use crate::model::diesel::dict::dict_schema::*;
#[derive(Queryable,Debug,Serialize,Deserialize,Default)]
pub struct Test {
pub id: i64,
pub tags: i64,
}
this is the minimal main.rs entrypoint:
#[macro_use]
extern crate diesel;
mod model;
use diesel::{ ExpressionMethods, QueryDsl};
fn main() {
get_bill_book_account_sum();
}
pub fn get_bill_book_account_sum(){
use crate::diesel::GroupByDsl;
use diesel::dsl::max;
use crate::model::diesel::dict::dict_schema::test as bill_record_table;
let source_query = bill_record_table::table
.group_by(bill_record_table::id)
.select((max(bill_record_table::tags),bill_record_table::id))
.filter(bill_record_table::dsl::tags.eq(9));
}
change the aggregate query like this fixed this problem:
pub fn get_bill_book_account_sum(request: &BillAccountRequest) -> Result<Vec<(i64, i32)>, diesel::result::Error>{
use crate::diesel::GroupByDsl;
use crate::model::diesel::fortune::fortune_schema::bill_record as bill_record_table;
let source_query = bill_record_table::table
.group_by(bill_record_table::account_id)
.select((diesel::dsl::sql::<diesel::sql_types::BigInt>("SUM(CAST(amount AS Integer))"),bill_record_table::account_id))
.filter(bill_record_table::dsl::bill_book_id.eq(request.bill_book_id));
let result = source_query.load::<(i64,i32)>(&get_connection());
return result;
}
the solution come from this issue. This is the answer come from the maintainer that shows diesel 1.x did not support group by official.
I'm learning to use diesel orm library, my database uses DECIMAL(8,2) type, but when I use Decimal in my model, I get an error
I am using Decimal provided by rust_decimal
diesel = { version="1.4.8", features = ["mysql", "r2d2", "chrono", "numeric"] }
rust_decimal = { version ="1.23", features = ["serde-with-str", "db-diesel-mysql"] }
rust_decimal_macros = "1.23"
my mysql table
CREATE TABLE `books` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(20) NOT NULL ,
`price` DECIMAL(8,2) UNSIGNED NOT NULL ,
`user_id` BIGINT UNSIGNED NOT NULL ,
`type` TINYINT(1) UNSIGNED DEFAULT '1' NOT NULL,
`create_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_at` DATETIME on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB ;
diesel generated schema
table! {
books (id) {
id -> Unsigned<Bigint>,
name -> Varchar,
price -> Unsigned<Decimal>,
user_id -> Unsigned<Bigint>,
#[sql_name = "type"]
type_ -> Unsigned<Tinyint>,
create_at -> Datetime,
update_at -> Datetime,
}
}
use crate::prelude::*;
use crate::schema::books;
use chrono::NaiveDateTime;
pub use rust_decimal::Decimal;
#[derive(Identifiable, Queryable, Serialize, Deserialize, Debug, Clone)]
#[table_name = "books"]
pub struct Book {
pub id: PK,
pub name: String,
pub price: Decimal,
pub user_id: PK,
pub type_: u8,
pub create_at: NaiveDateTime,
pub update_at: NaiveDateTime,
}
This is the error I get when I run cargo check
error[E0277]: the trait bound `rust_decimal::Decimal: FromSql<diesel::sql_types::Unsigned<diesel::sql_types::Numeric>, Mysql>` is not satisfied
--> src/controller/api/book.rs:19:25
|
19 | Ok(books::table.load::<models::book::Book>(&conn)?)
| ^^^^ the trait `FromSql<diesel::sql_types::Unsigned<diesel::sql_types::Numeric>, Mysql>` is not implemented for `rust_decimal::Decimal`
|
= help: the following implementations were found:
<rust_decimal::Decimal as FromSql<diesel::sql_types::Numeric, Mysql>>
= note: required because of the requirements on the impl of `Queryable<diesel::sql_types::Unsigned<diesel::sql_types::Numeric>, Mysql>` for `rust_decimal::Decimal`
= note: 2 redundant requirements hidden
= note: required because of the requirements on the impl of `Queryable<(diesel::sql_types::Unsigned<BigInt>, diesel::sql_types::Text, diesel::sql_types::Unsigned<diesel::sql_types::Numeric>, diesel::sql_types::Unsigned<BigInt>, diesel::sql_types::Unsigned<TinyInt>, diesel::sql_types::Datetime, diesel::sql_types::Datetime), Mysql>` for `Book`
= note: required because of the requirements on the impl of `LoadQuery<_, Book>` for `books::table`
note: required by a bound in `load`
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-1.4.8/src/query_dsl/mod.rs:1238:15
|
1238 | Self: LoadQuery<Conn, U>,
| ^^^^^^^^^^^^^^^^^^ required by this bound in `load`
For more information about this error, try `rustc --explain E0277`.
warning: `actix_backend` (bin "server") generated 6 warnings
error: could not compile `actix_backend` due to previous error; 6 warnings emitted
This is the rust version I'm using now
cargo --version
cargo 1.60.0 (d1fd9fe 2022-03-01)
I have also tried using bigdecimal also getting the same error
According to the documentation of diesel::sql_types::Unsigned<T> diesel does not provide builtin support for Unsigned<Decimal>. (There are no specific ToSql/FromSql/AsExpression impls listed on that page, in contrast to for example Unsigned<Integer>.) The same is true for rust_numeric::Decimal (Also only a FromSql/ToSql impl for Numeric/Decimal no one for Unsigned<Decimal>.
That all means neither of the crates support an Unsigned<Decimal> column out of the box. You can provide support for such columns by implementing the corresponding traits on your on your own. That means implementing FromSql/ToSql + deriving AsExpression/FromSqlRow for the corresponding new type wrapper.
That would result in code like this:
use diesel::sql_types::{Unsigned, Decimal};
use diesel::serialize::{self, ToSql};
use diesel::deserialize::{self, FromSql};
use diesel::mysql::Mysql;
#[derive(AsExpression, FromSqlRow)]
#[sql_type = "Unsigned<Decimal>"]
struct DecimalWrapper(rust_decimal::Decimal);
impl FromSql<Unsigned<Decimal>, Mysql> for DecimalWrapper {
fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
<rust_decimal::Decimal as FromSql<Decimal, Mysql>>::from_sql(bytes).map(Self)
}
}
impl ToSql<Unsigned<Decimal>, Mysql> for DecimalWrapper {
fn to_sql<W: Write>(&self, out: &mut serialize::Output<'_, W, DB>) -> serialize::Result {
<_ as ToSql<Decimal, Mysql>>::to_sql(&self.0, out)
}
}
This question already has answers here:
How do I fix "cannot find derive macro in this scope"?
(1 answer)
Why is a trait not implemented for a type that clearly has it implemented?
(1 answer)
Closed 2 years ago.
I'm trying to make a simple endpoint using Rocket. My Cargo.toml has these dependencies:
[dependencies]
rocket = "0.4.2"
rocket_codegen = "0.4.2"
rocket_contrib = "0.4.2"
main.rs looks like:
#[macro_use]
extern crate rocket;
use rocket_contrib::json::Json;
use serde::Serialize;
#[get("/org")]
fn getorg() -> Json<Org> {
Json(Org {
id: Option::from(25),
name: "Incredible-Customer".to_string(),
})
}
#[derive(Serialize)]
pub struct Org {
pub id: Option<i32>,
pub name: String,
}
fn main() {
rocket::ignite().mount("/", routes![getorg]).launch();
}
Compiling results in the errors:
error[E0432]: unresolved import `serde`
--> src/main.rs:3:5
|
3 | use serde::Serialize;
| ^^^^^ use of undeclared crate or module `serde`
error: cannot determine resolution for the derive macro `Serialize`
--> src/main.rs:14:10
|
14 | #[derive(Serialize)]
| ^^^^^^^^^
|
= note: import resolution is stuck, try simplifying macro imports
error[E0658]: `macro` is experimental
--> src/main.rs:7:1
|
7 | #[get("/org")]
| ^^^^^^^^^^^^^^
|
= note: see issue #39412 <https://github.com/rust-lang/rust/issues/39412> for more information
= help: add `#![feature(decl_macro)]` to the crate attributes to enable
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `Org: serde::ser::Serialize` is not satisfied
--> src/main.rs:8:16
|
8 | fn getorg() -> Json<Org> {
| ^^^^^^^^^ the trait `serde::ser::Serialize` is not implemented for `Org`
|
::: /Users/shep/.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.4.5/src/handler.rs:202:20
|
202 | pub fn from<T: Responder<'r>>(req: &Request, responder: T) -> Outcome<'r> {
| ------------- required by this bound in `handler::<impl rocket::Outcome<rocket::Response<'r>, rocket::http::Status, rocket::Data>>::from`
|
= note: required because of the requirements on the impl of `Responder<'_>` for `rocket_contrib::json::Json<Org>
I'm very confused as to how to look into this error. Is it a dependency issue? Why? I have versioned the rocket dependencies to the same one, but apparently this serde dependency is unhappy. Googling around claims it's a version mismatch inside one of my dependencies - but how do I go about solving that myself?
Add serde = {version = "1.0", features = ["derive"]} and serde_json = {version = "1.0"} to your cargo.toml to be able to derive from Serialize and Deserialize