SeaQL / sea-orm

🐚 An async & dynamic ORM for Rust
https://www.sea-ql.org/SeaORM/
Apache License 2.0
6.96k stars 486 forks source link

SelectorRaw doesn't pass binded values from SelectStatement to Paginator #663

Closed npapapietro closed 2 years ago

npapapietro commented 2 years ago

Description

When passing a raw sql query to Selector raw and paginating it, the values binded don't get passed down to the methods on paginator.

Steps to Reproduce

use sea_orm::{*, entity::prelude::*, sea_query::*};
mod users {
    use super::*;

    #[derive(Clone, Debug, DeriveEntityModel)]
    #[sea_orm(table_name = "users")]
    pub struct Model {
        #[sea_orm(primary_key, auto_increment = false)]
        pub id: Uuid,
        #[sea_orm(column_type = "Text", unique)]
        pub user_name: String,
    }
    impl ActiveModelBehavior for ActiveModel {}
}

fn main(){
    let db: DatabaseConnection = Database::connect("postgres://postgres:postgres@localhost:5432/postgres").await.unwrap();
    let builder = db.clone().get_database_backend();
    let qry_stmt =
        users::Entity::find().filter(users::Column::UserName.eq("myuser".to_string()));
    let select_stmt = SelectStatement::new()
        .column((Alias::new("inner_users"), Alias::new("user_name")))
        .from_subquery(qry_stmt.into_query(), Alias::new("inner_users"))
        .to_owned();

    let stmt = builder.build(&select_stmt);

    let query = users::Entity::find()
        .from_raw_sql(stmt)
        .into_json()
        .paginate(db, 5);

    if let Err(msg) = query.fetch_page(0).await {
        println!("{}", msg); // catches here
    }
    if let Err(msg) = query.num_pages().await {
        println!("{}", msg); // catches here
    }
    if let Err(msg) = query.num_items().await {
        println!("{}", msg); // catches here
    }
}

Expected Behavior

Pagination runs like Selector<T>

Actual Behavior

On the fetch_page method the error operator does not exist: text = bigint is returned. This is because the values from the actual query aren't present and the limit and offset are pushed on to the values list and mismatched with SelectStatement.values

For num_items and num_pages you get error returned from database: bind message supplies 0 parameters, but prepared statement "sqlx_s_1" requires 1

Reproduces How Often

Every run

Versions

0.7.1

Additional Information

Same behavior on SelectorRaw::into_json and SelectorRaw::into_model<T>

tyt2y3 commented 2 years ago

Can you create a PR and put a runnable example under issues/663? It would greatly help us in fixing the bug. And it'd be great if the snippet can be trimmed down a bit more. Is subquery a key factor here?

npapapietro commented 2 years ago

I'm not sure what's causing it, I'm learning the layout of this repo and attempting to nail it down. It could very well be the subquery component I have here. I added a PR with some unit tests that should capture the bug. The mock test had me going for a minute thinking I was missing something, but the integration test throws the error I was encountering.

billy1624 commented 2 years ago

Fixed by