volatiletech / sqlboiler

Generate a Go ORM tailored to your database schema.
BSD 3-Clause "New" or "Revised" License
6.74k stars 545 forks source link

Multi level eager failing #50

Closed jseriff closed 8 years ago

jseriff commented 8 years ago

When attempting a multi-level eager load, I am seeing a reflection error. Here is a reproduction case:

I constructed a simple 3 level hierarchy to show this error:

CREATE SCHEMA test_schema;

CREATE TABLE test_schema.parents (
    id BIGSERIAL PRIMARY KEY,
    name TEXT
);

CREATE TABLE test_schema.children (
    id BIGSERIAL PRIMARY KEY,
    parent_id BIGINT REFERENCES test_schema.parents(id),
    name TEXT
);

CREATE TABLE test_schema.third (
    id BIGSERIAL PRIMARY KEY,
    children_id BIGINT REFERENCES test_schema.children(id),
    name TEXT
);

INSERT INTO test_schema.parents (name) values ('P1');
INSERT INTO test_schema.parents (name) values ('P2');
INSERT INTO test_schema.children (parent_id, name) values ((select id from test_schema.parents where name = 'P1'), 'C11');
INSERT INTO test_schema.children (parent_id, name) values ((select id from test_schema.parents where name = 'P2'), 'C21');
INSERT INTO test_schema.children (parent_id, name) values ((select id from test_schema.parents where name = 'P2'), 'C22');
INSERT INTO test_schema.third (children_id, name) values ((select id from test_schema.children where name = 'C21'), 'T211');
INSERT INTO test_schema.third (children_id, name) values ((select id from test_schema.children where name = 'C21'), 'T212');

Generated the models on this schema, and then ran a the following code:

package main

import (
    "database/sql"

    "github.com/jseriff/sqltest/models"
    _ "github.com/lib/pq"
    "github.com/vattle/sqlboiler/queries/qm"
)

func main() {
    db, _ := sql.Open("postgres", "postgres://evsr_development:evsr_development@localhost:5432/evsr_development?options=+-c+search_path%%3Dtest_schema")

    _, _ = models.Parents(db,
        qm.Load("Children.Thirds"),
    ).All()
}

I receive the following error:

panic: reflect.Value.Addr of unaddressable value

goroutine 1 [running]:
panic(0x2acb60, 0xc4201ba2a0)
    /usr/local/Cellar/go/1.7/libexec/src/runtime/panic.go:500 +0x1a1
reflect.Value.Addr(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    /usr/local/Cellar/go/1.7/libexec/src/reflect/value.go:239 +0xbc
github.com/vattle/sqlboiler/queries.loadRelationshipState.loadRelationshipsRecurse(0x4546c0, 0xc420016630, 0xc4200db260, 0xc42011e920, 0x2, 0x2, 0x1, 0x2e2bc0, 0xc4200db200, 0x199, ...)
    /Users/jseriff/go/src/github.com/vattle/sqlboiler/queries/eager_load.go:145 +0x337
github.com/vattle/sqlboiler/queries.loadRelationshipState.loadRelationships(0x4546c0, 0xc420016630, 0xc4200db260, 0xc42011e920, 0x2, 0x2, 0x1, 0x2eaf60, 0xc420014d20, 0x2, ...)
    /Users/jseriff/go/src/github.com/vattle/sqlboiler/queries/eager_load.go:126 +0x2c3
github.com/vattle/sqlboiler/queries.(*Query).Bind(0xc4200a9b80, 0x2eaf60, 0xc420014d20, 0x0, 0x0)
    /Users/jseriff/go/src/github.com/vattle/sqlboiler/queries/reflect.go:123 +0x2d6
github.com/jseriff/sqltest/models.parentQuery.All(0xc4200a9b80, 0xc420016630, 0xc42000d660, 0x2, 0x2, 0xc4200a9b80)
    /Users/jseriff/go/src/github.com/jseriff/sqltest/models/parents.go:254 +0x71
main.main()
    /Users/jseriff/go/src/github.com/jseriff/sqltest/main.go:16 +0xea
exit status 2

I spent a few minutes looking into loadRelationships - it looks like when it recurses, the loadRelationshipsRecurse method is expecting to receive the "Children"'s R, but instead receives the "Parent"s R, which does not have a Thirds member.

aarondl commented 8 years ago

Hey @jseriff. I looked into this today. I haven't finished fixing it because I was quite busy and there's another complicated problem that surfaced underneath this one. Will try to get it fixed soon though :) Half-fixed on my local atm.

aarondl commented 8 years ago

Your sample program now runs correctly, and does the most efficient queries we can without joins.

SELECT * FROM "test_schema"."parents";
[]
load rels models.Parent [Children Thirds]
!loaded Children
loadChildren!
select * from "test_schema"."children" where "parent_id" in ($1,$2)
[1 2]
collection type models.ChildSlice
load rels models.Child [Thirds]
!loaded Thirds
loadThirds!
select * from "test_schema"."third" where "children_id" in ($1,$2,$3)
[1 2 3]

I'm not ultra-confident this will work in all cases because my tests are a bit weak because I ran out of time tonight. Might revise this later. Will fix your other bug tomorrow. Do you mind trying the new code? :)

aarondl commented 8 years ago

Fixed tests and one more bug this morning.

jseriff commented 8 years ago

This issue appears to be solved on dev. Thanks!