lambdaisland / facai

Factories for fun and profit. 恭喜發財!
Mozilla Public License 2.0
45 stars 1 forks source link

Custom JDBC table config lost when child relationships deferred #7

Open denismccarthykerry opened 2 years ago

denismccarthykerry commented 2 years ago

Consider a typical foreign key relationship between two tables like this:

--Database tables:

create table child
(
    child_id    varchar(40) not null primary key,
    description varchar(200)
);

create table parent
(
    parent_id   varchar(40) not null
        primary key,
    child_id    varchar(40) not null
        references child,
    parent_desc varchar(500)
);

, with factories defined like so:

  (f/defactory child
    :lambdaisland.facai.next-jdbc/table "child"
    :facai.factoryory/primary-key :child-id
    {:child-id #(str (random-uuid))
     :description "This is the description"}
    :traits
    {:bar
     {:with {:description "bar"}}})

  (f/defactory parent
    :lambdaisland.facai.next-jdbc/table "parent"
    :facai.factoryory/primary-key :parent-id
    {:parent-id #(str (random-uuid))
     :child child
     :parent-desc  #(str (random-uuid))}
    :traits
    {:foo
     {:with {:parent-desc "foo"}}})

when attempting to create! sample data in Postgres using the lambdaisland.next.jdbc namespace like so:

(fnj/create! {::fnj/ds ds
                ::fnj/fk-col-fn #(keyword (str (name %) "-id"))}
                parent {
                        :with {:child (lambdaisland.facai.kernel/defer child {:traits [:bar]})}})

a Postgres Exception is thrown:

Execution error (PSQLException) at org.postgresql.core.v3.QueryExecutorImpl/receiveErrorResponse (QueryExecutorImpl.java:2676).
ERROR: relation "children" does not exist
  Position: 13
  Location: File: parse_relation.c, Routine: parserOpenTable, Line: 1376
  Server SQLState: 42P01

This implies that the :lambdaisland.facai.next-jdbc/table value in the child factory is not being used, as would be expected in this configuration. This works for the standard case with no defer on the child factory, so it is probably related to the deferral.

plexus commented 1 year ago

Thanks for the report, I had a look but it isn't immediately trivial to fix, and I don't want to put much more effort into Facai. I also failed to get your example to run on H2, that would have helped a lot since it would've been easier to add a failing test case first.

Facai turned out to be a great proof of concept, but dogfooding it for a while did show it has some fundamental issues. One of them is the deferred abstraction which we're likely to get rid of.

I'm leaving Facai mostly as-is since it's used on a few dozen projects at this point, but any future effort will go towards a redesign in the form of Harvest.