Skip to content

Commit

Permalink
don't allow nested preloads to attempt to relations that return non-t…
Browse files Browse the repository at this point in the history
…able types
  • Loading branch information
leafo committed Nov 1, 2024
1 parent 128a245 commit a13caec
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 12 deletions.
38 changes: 31 additions & 7 deletions lapis/db/model/relations.lua
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,7 @@ preload_homogeneous = function(sub_relations, model, objects, preload_spec, ...)
preload_relation(model, objects, relation_name, preload_opts)
if not (val_type == "boolean" or val_type == "function") then
sub_relations = sub_relations or { }
local _update_0 = val
sub_relations[_update_0] = sub_relations[_update_0] or { }
local loaded_objects = sub_relations[val]
local loaded_objects = sub_relations[val] or { }
if r.has_many or r.fetch and r.many then
for _index_0 = 1, #objects do
local _continue_1 = false
Expand All @@ -120,8 +118,19 @@ preload_homogeneous = function(sub_relations, model, objects, preload_spec, ...)
end
local _list_0 = obj[relation_name]
for _index_1 = 1, #_list_0 do
local fetched = _list_0[_index_1]
table.insert(loaded_objects, fetched)
local _continue_2 = false
repeat
local fetched = _list_0[_index_1]
if not (type(fetched) == "table") then
_continue_2 = true
break
end
table.insert(loaded_objects, fetched)
_continue_2 = true
until true
if not _continue_2 then
break
end
end
_continue_1 = true
until true
Expand All @@ -131,10 +140,25 @@ preload_homogeneous = function(sub_relations, model, objects, preload_spec, ...)
end
else
for _index_0 = 1, #objects do
local obj = objects[_index_0]
table.insert(loaded_objects, obj[relation_name])
local _continue_1 = false
repeat
local obj = objects[_index_0]
local fetched = obj[relation_name]
if not (type(fetched) == "table") then
_continue_1 = true
break
end
table.insert(loaded_objects, fetched)
_continue_1 = true
until true
if not _continue_1 then
break
end
end
end
if next(loaded_objects) and not sub_relations[val] then
sub_relations[val] = loaded_objects
end
end
end
_continue_0 = true
Expand Down
11 changes: 8 additions & 3 deletions lapis/db/model/relations.moon
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,23 @@ preload_homogeneous = (sub_relations, model, objects, preload_spec, ...) ->
-- Ignore the val_types that we know can not contain nested relations
unless val_type == "boolean" or val_type == "function"
sub_relations or= {}
sub_relations[val] or= {}
loaded_objects = sub_relations[val]
loaded_objects = sub_relations[val] or {}

-- grab all the loaded objects to process
if r.has_many or r.fetch and r.many
for obj in *objects
continue unless obj[relation_name] -- if the preloader didn't insert array then just skip
for fetched in *obj[relation_name]
continue unless type(fetched) == "table"
table.insert loaded_objects, fetched
else
for obj in *objects
table.insert loaded_objects, obj[relation_name]
fetched = obj[relation_name]
continue unless type(fetched) == "table"
table.insert loaded_objects, fetched

if next(loaded_objects) and not sub_relations[val]
sub_relations[val] = loaded_objects

when "string"
-- preload_spec is simply the name of the relation to preload
Expand Down
30 changes: 28 additions & 2 deletions spec/relations_spec.moon
Original file line number Diff line number Diff line change
Expand Up @@ -1816,14 +1816,40 @@ describe "lapis.db.model.relations", ->
[[SELECT * FROM "user_data" WHERE "user_id" IN (11, 12)]]
}, sorted: true

it "preloads a fetch that returns basic value", ->
class Items extends Model
@relations: {
{"things",
many: true
fetch: => error "should not be called"
preload: (items, ...) ->
for item in *items
item.things = {true, true, false}
}


{"thing",
fetch: => error "should not be called"
preload: (items, ...) ->
for item in *items
item.thing = true -- store a boolean
}
}

items = {Items!}
preload items, things: {}, thing: {}
assert.same {true, true, false}, items[1].things
assert.same true, items[1].thing


it "passes preload opts to fetch relation", ->
local preload_objects, preload_opts

class Item extends Model
@relations: {
{"things",
many: true
fetch: => error "no fetch me"
fetch: => error "should not be called"
preload: (...) ->
preload_objects, preload_opts = ...
}
Expand All @@ -1846,7 +1872,7 @@ describe "lapis.db.model.relations", ->
random: "option"
}, preload_opts

it "with skip_included preload option", ->
it "with skip_included preload option #ddd", ->
models.Items = class Items extends Model
@relations: {
{"parents", has_many: "Items", key: "parent_id"}
Expand Down

0 comments on commit a13caec

Please sign in to comment.