Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

table have more than one primary_key can not use on_conflict(diesel::dsl::DuplicatedKeys) #3872

Closed
3 tasks done
Caisin opened this issue Dec 10, 2023 · 7 comments
Closed
3 tasks done

Comments

@Caisin
Copy link

Caisin commented Dec 10, 2023

Setup

schema.rs

diesel::table! {
    sys_api (path, method) {
        #[max_length = 255]
        path -> Varchar,
        #[max_length = 50]
        method -> Varchar,
        #[max_length = 50]
        name -> Varchar,
        #[max_length = 50]
        scope -> Varchar,
        #[max_length = 10]
        state -> Varchar,
    }
}

models.rs

#[derive(
    Clone,
    Debug,
    Serialize,
    Deserialize,
    Default,
    PartialEq,
    Queryable,
    Insertable,
    Identifiable,
    AsChangeset,
)]
#[diesel(table_name = sys_api)]
#[diesel(primary_key(path,method))]
pub struct SysApi {
    pub id: u64,
    pub path: String,
    pub method: String,
    pub name: String,
    pub scope: String,
    pub state: String,
}

Versions

  • **Rust:**1.76
  • **Diesel:**2.14
  • **Database:**mysql
  • Operating Systemwindows

Feature Flags

  • diesel:

Problem Description

table have more than one primary_key can not use on_conflict(diesel::dsl::DuplicatedKeys)

What are you trying to accomplish?

What is the expected output?

What is the actual output?

 Diesel,
     |     ^^^^^^ the trait `QueryFragment<diesel::mysql::Mysql, mysql::backend::MysqlOnConflictClause>` is not implemented for `query_builder::upsert::on_conflict_clause::OnConflictValues<query_builder::insert_statement::ValuesClause<(DefaultableColumnInsertValue<ColumnInsertValue<schema::sys_api::columns::path, expression::bound::Bound<Text, &std::string::String>>>, DefaultableColumnInsertValue<ColumnInsertValue<schema::sys_api::columns::method, expression::bound::Bound<Text, &std::string::String>>>, DefaultableColumnInsertValue<ColumnInsertValue<schema::sys_api::columns::name, expression::bound::Bound<Text, &std::string::String>>>, DefaultableColumnInsertValue<ColumnInsertValue<schema::sys_api::columns::scope, expression::bound::Bound<Text, &std::string::String>>>, DefaultableColumnInsertValue<ColumnInsertValue<schema::sys_api::columns::state, expression::bound::Bound<Text, &std::string::String>>>), schema::sys_api::table>, query_builder::upsert::on_conflict_target::ConflictTarget<DuplicatedKeys>, query_builder::upsert::on_conflict_actions::DoUpdate<(query_builder::update_statement::changeset::Assign<query_builder::update_statement::changeset::ColumnWrapperForUpdate<schema::sys_api::columns::name>, SqlLiteral<Text>>, query_builder::update_statement::changeset::Assign<query_builder::update_statement::changeset::ColumnWrapperForUpdate<schema::sys_api::columns::scope>, SqlLiteral<Text>>, query_builder::update_statement::changeset::Assign<query_builder::update_statement::changeset::ColumnWrapperForUpdate<schema::sys_api::columns::state>, SqlLiteral<Text>>), schema::sys_api::table>>`
     |
     = help: the following other types implement trait `QueryFragment<DB, SP>`:
               <query_builder::upsert::on_conflict_clause::OnConflictValues<Values, Target, Action> as QueryFragment<diesel::mysql::Mysql, mysql::backend::MysqlOnConflictClause>>
               <query_builder::upsert::on_conflict_clause::OnConflictValues<Values, Target, Action> as QueryFragment<DB>>
               <query_builder::upsert::on_conflict_clause::OnConflictValues<Values, Target, Action> as QueryFragment<DB, SD>>
               <query_builder::upsert::on_conflict_clause::OnConflictValues<Values, Target, Action, query_builder::where_clause::WhereClause<Expr>> as QueryFragment<DB>>
     = note: required for `OnConflictValues<ValuesClause<(DefaultableColumnInsertValue<ColumnInsertValue<path, Bound<Text, &String>>>, ..., ..., ..., ...), ...>, ..., ...>` to implement `QueryFragment<diesel::mysql::Mysql>`
     = note: the full type name has been written to 'D:\code\rust\cx\target\debug\deps\cx_biz_sys-6a229df924011786.long-type-17862108743910028546.txt'
     = note: 1 redundant requirement hidden
     = note: required for `InsertStatement<table, OnConflictValues<ValuesClause<(DefaultableColumnInsertValue<ColumnInsertValue<path, ...>>, ..., ..., ..., ...), ...>, ..., ...>>` to implement `QueryFragment<diesel::mysql::Mysql>`
     = note: the full type name has been written to 'D:\code\rust\cx\target\debug\deps\cx_biz_sys-6a229df924011786.long-type-2431980552689726686.txt'
     = note: required for `InsertStatement<table, OnConflictValues<ValuesClause<(DefaultableColumnInsertValue<ColumnInsertValue<path, ...>>, ..., ..., ..., ...), ...>, ..., ...>>` to implement `ExecuteDsl<PooledConnection<ConnectionManager<MysqlConnection>>, diesel::mysql::Mysql>`
     = note: the full type name has been written to 'D:\code\rust\cx\target\debug\deps\cx_biz_sys-6a229df924011786.long-type-2431980552689726686.txt'
note: required by a bound in `diesel::RunQueryDsl::execute`
    --> D:\code\rust\diesel\diesel\src\query_dsl\mod.rs:1431:15
     |
1428 |     fn execute(self, conn: &mut Conn) -> QueryResult<usize>
     |        ------- required by a bound in this associated function
...
1431 |         Self: methods::ExecuteDsl<Conn>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::execute`
     = note: this error originates in the derive macro `Diesel` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.

Are you seeing any additional errors?

Steps to reproduce

Checklist

  • This issue can be reproduced on Rust's stable channel. (Your issue will be
    closed if this is not the case)
  • This issue can be reproduced without requiring a third party crate
@Caisin Caisin added the bug label Dec 10, 2023
@weiznich
Copy link
Member

Thanks for opening this issue. Please provide all the relevant code that is necessary to reproduce your error message, as otherwise it's hard/impossible for anyone to see what's wrong here. Also please provide the complete error message as emitted by rustc. Based on the provided part of the error message it seems to miss relevant information (like line information and code snippet of the actual error.)

@Caisin
Copy link
Author

Caisin commented Dec 11, 2023

FAIL code

schema.rs

diesel::table! {
    sys_api (path, method) {
        #[max_length = 255]
        path -> Varchar,
        #[max_length = 50]
        method -> Varchar,
        #[max_length = 50]
        name -> Varchar,
        #[max_length = 50]
        scope -> Varchar,
        #[max_length = 10]
        state -> Varchar,
    }
}

models.rs

#[derive(
    Clone,
    Debug,
    Serialize,
    Deserialize,
    Default,
    PartialEq,
    Queryable,
    Insertable,
    Identifiable,
    AsChangeset,
)]
#[diesel(table_name = sys_api)]
#[diesel(primary_key(path,method))]
pub struct SysApi {
    pub path: String,
    pub method: String,
    pub name: String,
    pub scope: String,
    pub state: String,
}

insert into code

let v = SysApi::default();
diesel::insert_into(sys_api)
            .values(&v)
            .on_conflict(diesel::dsl::DuplicatedKeys)
            .do_update()
            .set(&v)
            .execute(con)?;

error log


Diesel,
     |     ^^^^^^ the trait `QueryFragment<diesel::mysql::Mysql, mysql::backend::MysqlOnConflictClause>` is not implemented for `query_builder::upsert::on_conflict_clause::OnConflictValues<query_builder::insert_statement::ValuesClause<(DefaultableColumnInsertValue<ColumnInsertValue<schema::sys_api::columns::path, expression::bound::Bound<Text, &std::string::String>>>, DefaultableColumnInsertValue<ColumnInsertValue<schema::sys_api::columns::method, expression::bound::Bound<Text, &std::string::String>>>, DefaultableColumnInsertValue<ColumnInsertValue<schema::sys_api::columns::name, expression::bound::Bound<Text, &std::string::String>>>, DefaultableColumnInsertValue<ColumnInsertValue<schema::sys_api::columns::scope, expression::bound::Bound<Text, &std::string::String>>>, DefaultableColumnInsertValue<ColumnInsertValue<schema::sys_api::columns::state, expression::bound::Bound<Text, &std::string::String>>>), schema::sys_api::table>, query_builder::upsert::on_conflict_target::ConflictTarget<DuplicatedKeys>, query_builder::upsert::on_conflict_actions::DoUpdate<(query_builder::update_statement::changeset::Assign<query_builder::update_statement::changeset::ColumnWrapperForUpdate<schema::sys_api::columns::name>, SqlLiteral<Text>>, query_builder::update_statement::changeset::Assign<query_builder::update_statement::changeset::ColumnWrapperForUpdate<schema::sys_api::columns::scope>, SqlLiteral<Text>>, query_builder::update_statement::changeset::Assign<query_builder::update_statement::changeset::ColumnWrapperForUpdate<schema::sys_api::columns::state>, SqlLiteral<Text>>), schema::sys_api::table>>`
     |
     = help: the following other types implement trait `QueryFragment<DB, SP>`:
               <query_builder::upsert::on_conflict_clause::OnConflictValues<Values, Target, Action> as QueryFragment<diesel::mysql::Mysql, mysql::backend::MysqlOnConflictClause>>
               <query_builder::upsert::on_conflict_clause::OnConflictValues<Values, Target, Action> as QueryFragment<DB>>
               <query_builder::upsert::on_conflict_clause::OnConflictValues<Values, Target, Action> as QueryFragment<DB, SD>>
               <query_builder::upsert::on_conflict_clause::OnConflictValues<Values, Target, Action, query_builder::where_clause::WhereClause<Expr>> as QueryFragment<DB>>
     = note: required for `OnConflictValues<ValuesClause<(DefaultableColumnInsertValue<ColumnInsertValue<path, Bound<Text, &String>>>, ..., ..., ..., ...), ...>, ..., ...>` to implement `QueryFragment<diesel::mysql::Mysql>`
     = note: the full type name has been written to 'D:\code\rust\cx\target\debug\deps\cx_biz_sys-6a229df924011786.long-type-17862108743910028546.txt'
     = note: 1 redundant requirement hidden
     = note: required for `InsertStatement<table, OnConflictValues<ValuesClause<(DefaultableColumnInsertValue<ColumnInsertValue<path, ...>>, ..., ..., ..., ...), ...>, ..., ...>>` to implement `QueryFragment<diesel::mysql::Mysql>`
     = note: the full type name has been written to 'D:\code\rust\cx\target\debug\deps\cx_biz_sys-6a229df924011786.long-type-2431980552689726686.txt'
     = note: required for `InsertStatement<table, OnConflictValues<ValuesClause<(DefaultableColumnInsertValue<ColumnInsertValue<path, ...>>, ..., ..., ..., ...), ...>, ..., ...>>` to implement `ExecuteDsl<PooledConnection<ConnectionManager<MysqlConnection>>, diesel::mysql::Mysql>`
     = note: the full type name has been written to 'D:\code\rust\cx\target\debug\deps\cx_biz_sys-6a229df924011786.long-type-2431980552689726686.txt'
note: required by a bound in `diesel::RunQueryDsl::execute`
    --> D:\code\rust\diesel\diesel\src\query_dsl\mod.rs:1431:15
     |
1428 |     fn execute(self, conn: &mut Conn) -> QueryResult<usize>
     |        ------- required by a bound in this associated function
...
1431 |         Self: methods::ExecuteDsl<Conn>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::execute`
     = note: this error originates in the derive macro `Diesel` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.

when id use one Field primary_key this code cargo check pass

Pass Code

schema.rs

diesel::table! {
    sys_api (id) {
        id -> Unsigned<BigInt>,
        #[max_length = 255]
        path -> Varchar,
        #[max_length = 50]
        method -> Varchar,
        #[max_length = 50]
        name -> Varchar,
        #[max_length = 50]
        scope -> Varchar,
        #[max_length = 10]
        state -> Varchar,
    }
}

models.rs

#[derive(
    Clone,
    Debug,
    Serialize,
    Deserialize,
    Default,
    PartialEq,
    Queryable,
    Insertable,
    Identifiable,
    AsChangeset,
)]
#[diesel(table_name = sys_api)]
#[diesel(primary_key(id))]
pub struct SysApi {
    pub id: u64,
    pub path: String,
    pub method: String,
    pub name: String,
    pub scope: String,
    pub state: String,
}

insert into code

let v = SysApi::default();
diesel::insert_into(sys_api)
            .values(&v)
            .on_conflict(diesel::dsl::DuplicatedKeys)
            .do_update()
            .set(&v)
            .execute(con)?;

@Caisin
Copy link
Author

Caisin commented Dec 12, 2023

@weiznich please help confirm again

@weiznich
Copy link
Member

As this is a project run in my free time I can only work on stuff if I have time. That usually means that it can take several days/weeks/month until you hear back from me about something. Pinging me usually puts such things down on my priority list.

weiznich added a commit to weiznich/diesel that referenced this issue Dec 15, 2023
This commit changes some `QueryFragment` impls that previously assumed
that the provided primary key consist only of a single column. The new
implementation allows composite keys as well. In addition I also added
two tests to cover these cases as well.
@weiznich
Copy link
Member

I've added #3877 to fix this issue. Please check if that resolves your problem.

weiznich added a commit to weiznich/diesel that referenced this issue Dec 15, 2023
This commit changes some `QueryFragment` impls that previously assumed
that the provided primary key consist only of a single column. The new
implementation allows composite keys as well. In addition I also added
two tests to cover these cases as well.
weiznich added a commit to weiznich/diesel that referenced this issue Dec 15, 2023
This commit changes some `QueryFragment` impls that previously assumed
that the provided primary key consist only of a single column. The new
implementation allows composite keys as well. In addition I also added
two tests to cover these cases as well.
github-merge-queue bot pushed a commit that referenced this issue Dec 20, 2023
@weiznich
Copy link
Member

Closed by #3877

@Caisin
Copy link
Author

Caisin commented Dec 21, 2023

@weiznich 3q verify much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants