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

Eager loading causes DataTypeCasting exception on sqlite #403

Open
wonderix opened this issue Feb 12, 2022 · 10 comments · Fixed by #426
Open

Eager loading causes DataTypeCasting exception on sqlite #403

wonderix opened this issue Feb 12, 2022 · 10 comments · Fixed by #426
Labels

Comments

@wonderix
Copy link

Calling eager_load with sqlite always produces a DataTypeCasting Column <Model>.id can't be casted from Int64 to it's type - (Int32 | Nil).

I'm using a simple model with User, Team and Member and the following code is causing the exception

Team.all.eager_load(members: [:user])

This can be fixed by adding the following code in mapping.cr at line 438

--- a/src/jennifer/model/mapping.cr
+++ b/src/jennifer/model/mapping.cr
@@ -438,6 +438,8 @@ module Jennifer
               %casted_var{key.id} =
                 {% if value[:parsed_type] =~ /String/ %}
                   %var{key.id}
+                {% elsif value[:parsed_type] =~ /Int32/ %}
+                  (%var{key.id}.is_a?(Int64) ? %var{key.id}.to_i32 : %var{key.id})
                 {% else %}
                   (%var{key.id}.is_a?(String) ? self.class.coerce_{{key.id}}(%var{key.id}) : %var{key.id})
                 {% end %}

I'm not sure if this would be the right place for this kind of fix.

I'm using

  • crystal: 1.3.2
  • jennifer.cr: master
  • jennifer_sqlite3_adapter: 0.4.0
@imdrasil
Copy link
Owner

Hi, sorry for a delay. Does it mean that in all other cases everything is fine when you load your models separately? sqlite adapter master branch is behind current jennifer master branch. Recently we introduced a breaking change - automatic primary keys are of Int64 type.

@wonderix
Copy link
Author

wonderix commented Feb 14, 2022

Loading the models separately works fine. Only eager loading causes problems. I would say that my problem is related to this breaking change.

@imdrasil
Copy link
Owner

Will try to reproduce and fix on this weekend

@imdrasil
Copy link
Owner

Also could you please share minified mapping for your User, Team and Member models

@wonderix
Copy link
Author

class User < Jennifer::Model::Base
  mapping(
    id: Primary32,
    email: String?,
  )
  has_many :memberships, TeamMember
end

class TeamMember < Jennifer::Model::Base
  mapping(
    id: Primary32,
    user_id: Int32,
    team_id: Int32,
    role: Int32,
  )
  belongs_to :team, Team
  belongs_to :user, User
end

class Team < Jennifer::Model::Base
  mapping(
    id: Primary32,
    name: String,
  )
  has_many :members, TeamMember
end

@wonderix
Copy link
Author

Any updates on this issue?

@cyangle
Copy link
Contributor

cyangle commented Oct 4, 2022

I couldn't reproduce it with postgres. Maybe it's an issue with sqlite adapter.
Could you share your migration files?

Here's my test with postgres: cyangle@566fec0

@wonderix

@imdrasil
Copy link
Owner

imdrasil commented Oct 4, 2022

Was on a vacation so it look longer to respond 🌴 Hm, I though I had done something with this but don't remember what and why I left this without a response. Will take a look in the evening today

@imdrasil
Copy link
Owner

imdrasil commented Oct 4, 2022

I was able to reproduce it. Sorry, I don't remember why I skipped this 😞 . Will find a way to fix this behavior

@Victor7095
Copy link

The error still persists on latest releases
shards.yml

dependencies:
  kemal:
    github: kemalcr/kemal
  jennifer:
    github: imdrasil/jennifer.cr
    version: "~> 0.13.0"
  sqlite3:
    github: crystal-lang/crystal-sqlite3
    version: "0.18.0"
  jennifer_sqlite3_adapter:
    github: imdrasil/jennifer_sqlite3_adapter
    version: "~> 0.4.0"
  sam:
    github: imdrasil/sam.cr
    version: 0.4.2

Models:

class TravelPlan < Jennifer::Model::Base
  mapping(
    id: Primary32,
  )
  has_many :travel_stops, TravelStop, dependent: :destroy
end

class TravelStop < Jennifer::Model::Base
  mapping(
    id: Primary32,
    api_id: Int32,
    travel_plan_id: Int32?,
  )
  
  belongs_to :travel_plan, TravelPlan
end

Error: Exception: Column TravelPlan.id can't be casted from Int64 to it's type - (Int32 | Nil)
Code: travel_plan = TravelPlan.where { _id == id }.eager_load(:travel_stops).first!
Am I using the correct dependecy versions?

@imdrasil imdrasil reopened this Jun 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants