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

large composite key table #1294

Closed
billy1624 opened this issue Dec 9, 2022 Discussed in #1293 · 8 comments · Fixed by SeaQL/sea-query#564 or #1508
Closed

large composite key table #1294

billy1624 opened this issue Dec 9, 2022 Discussed in #1293 · 8 comments · Fixed by SeaQL/sea-query#564 or #1508
Assignees

Comments

@billy1624
Copy link
Member

Discussed in #1293

Originally posted by meowser December 9, 2022
I have a table I am working with which has a very large composite primary key. When I auto-generate a model using sea-orm-cli the created model causes the following error:

the trait `ValueType` is not implemented for `(std::string::String, std::string::String, std::string::String, std::string::String, std::string::String, std::string::String, std::string::String)

Here is an example of the model:

use sea_orm::entity::prelude::*;                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                             
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]                                                                                                                                                                                                                                                                                                                    
#[sea_orm(table_name = "example")]                                                                                                                                                                                                                                                                                                                                           
pub struct Model {                                                                                                                                                                                                                                                                                                                                                           
    #[sea_orm(primary_key, auto_increment = false)]                                                                                                                                                                                                                                                                                                                          
    pub a: String,                                                                                                                                                                                                                                                                                                                                                           
    #[sea_orm(primary_key, auto_increment = false)]                                                                                                                                                                                                                                                                                                                          
    pub b: String,                                                                                                                                                                                                                                                                                                                                                           
    #[sea_orm(primary_key, auto_increment = false)]                                                                                                                                                                                                                                                                                                                          
    pub c: String,                                                                                                                                                                                                                                                                                                                                                           
    #[sea_orm(primary_key, auto_increment = false)]                                                                                                                                                                                                                                                                                                                          
    pub d: String,                                                                                                                                                                                                                                                                                                                                                           
    #[sea_orm(primary_key, auto_increment = false)]                                                                                                                                                                                                                                                                                                                          
    pub e: String,                                                                                                                                                                                                                                                                                                                                                           
    #[sea_orm(primary_key, auto_increment = false)]                                                                                                                                                                                                                                                                                                                          
    pub f: String,                                                                                                                                                                                                                                                                                                                                                           
    #[sea_orm(primary_key, auto_increment = false)]                                                                                                                                                                                                                                                                                                                          
    pub g: String,                                                                                                                                                                                                                                                                                                                                                           
    pub h: String,                                                                                                                                                                                                                                                                                                                                                           
}                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                             
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]                                                                                                                                                                                                                                                                                                                      
pub enum Relation {}                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                             
impl ActiveModelBehavior for ActiveModel {}   

I notice if I take out one of the primary key attributes my code will compile, so I believe there is an six column primary key limit. I was wondering what would be the best approach for dealing with tables like this since I have quite a few tables with long composite keys, which I cannot change?

@billy1624
Copy link
Member Author

Hey @meowser, thanks for asking! Yes, the hard limit is 6 composite primary key.

https://github.com/SeaQL/sea-query/blob/83f548472894453afa6c8a5ab780a376a10bc710/src/value.rs#L246-L254

As a temporary solution, you can pick up to 6 columns to be the composite primary key. And leave other as ordinary columns.

I'll create a PR to bump the limit up to 10 this afternoon. Then, you can point your sea-orm to a git dependency if you don't mind.

@billy1624
Copy link
Member Author

billy1624 commented Dec 9, 2022

Somewhat related:

@meowser
Copy link

meowser commented Dec 9, 2022

Hey @meowser, thanks for asking! Yes, the hard limit is 6 composite primary key.

https://github.com/SeaQL/sea-query/blob/83f548472894453afa6c8a5ab780a376a10bc710/src/value.rs#L246-L254

As a temporary solution, you can pick up to 6 columns to be the composite primary key. And leave other as ordinary columns.

I'll create a PR to bump the limit up to 10 this afternoon. Then, you can point your sea-orm to a git dependency if you don't mind.

thanks!

@billy1624
Copy link
Member Author

Hey @tyt2y3, I want your opinion on this.

Currently, we have two similar list constructed in Enum:

The Dataflow

  • Input: tuple i.e. (a, b, c)
  • Storage: Enum with various size represented in Enum variants
  • Retrieval: tuple or Vec

The Concern

As the size of tuple increased, the Enum implementation waste more memory space. Because the memory size of a Enum is determined by its largest variant.

pub enum ValueTuple {
    One(Value),
    Two(Value, Value),
    Three(Value, Value, Value),
    Four(Value, Value, Value, Value),
    Five(Value, Value, Value, Value, Value),
    Six(Value, Value, Value, Value, Value, Value),
    Seven(Value, Value, Value, Value, Value, Value, Value),
    Eight(Value, Value, Value, Value, Value, Value, Value, Value),
    Nine(Value, Value, Value, Value, Value, Value, Value, Value, Value),
    Ten(Value, Value, Value, Value, Value, Value, Value, Value, Value, Value),
}

The memory needed to store ValueTuple::One is the same as ValueTuple::Ten.

The Proposal

We can swap the storage from Enum to Vec, this will greatly reduce memory waste. The conversion methods will be kept but to convert input tuple into Vec instead of Enum. We can still check the arity by calling Vec::len().

However, it will open a hole where an empty Vec is a potential. But I think normal user who instantiate through tuple won't fall into this.

@JonasCir
Copy link

Just a random thought: is it possible to add feature configurations to enum variants? Such that 7-10 is only compiled conditionally if you ask for it?

@billy1624
Copy link
Member Author

Just a random thought: is it possible to add feature configurations to enum variants? Such that 7-10 is only compiled conditionally if you ask for it?

Still, this isn't attacking the fundamental problem of it. And I think it's not a good use of feature hahaa.

@JonasCir
Copy link

True :D

@tyt2y3
Copy link
Member

tyt2y3 commented Dec 19, 2022

Yeah it started from a tuple of three which I think is the ideal size.

I don't want basic usage to be penalized, so potentially it can look like:

enum ValueTuple {
    One(Value),
    Two(Value, Value),
    Three(Value, Value, Value),
    Many(Vec<Value>),
}

This was referenced Dec 21, 2022
@billy1624 billy1624 self-assigned this Dec 21, 2022
@billy1624 billy1624 moved this to Triage in SeaQL Dev Tracker Dec 21, 2022
@billy1624 billy1624 reopened this Dec 22, 2022
@billy1624 billy1624 moved this from Triage to In Progress in SeaQL Dev Tracker Feb 24, 2023
@billy1624 billy1624 moved this from In Progress to Review in SeaQL Dev Tracker Feb 24, 2023
@github-project-automation github-project-automation bot moved this from Review to Done in SeaQL Dev Tracker Apr 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
4 participants