Eager loading causes DataTypeCasting exception on sqlite
wonderix opened this issue · 10 comments
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
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.
Loading the models separately works fine. Only eager loading causes problems. I would say that my problem is related to this breaking change.
Will try to reproduce and fix on this weekend
Also could you please share minified mapping for your User
, Team
and Member
models
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
Any updates on this issue?
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
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
I was able to reproduce it. Sorry, I don't remember why I skipped this 😞 . Will find a way to fix this behavior
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?