Hello.

The query-building logic for Rose::DB::Object::Manager->get_objects()
makes an assumption that I would like to politely question. :)

Suppose we have tables a, b, and c.  Table b has an FK to table a.
Table b also has an FK to table c.  These FK columns are all NOT NULL
constrained.  However, table b is not a "mapping" table for an n-to-n
relationship; it is a construct with its own meaning.  As one might
guess from these FKs, table a "has many" table b's, such that we would
register a one-to-many relationship from a to b.

Where I to use get_objects for table a, it would be reasonable to use a
with_objects setting of:
[qw( b b.c )]

However, this will fail to return any records for which table c cannot
be found, despite the fact that table c is requested as a member of
with_objects rather than require_objects.

Lines 901-906 of the Manager module reveal this to be explicitly by
design, with a comment indicating that "...Foreign keys that have all
non-null columns are never outer-joined...".  And the following
condition is pretty clear:
if (!($rel_type eq 'foreign_key' && $rel->is_required &&
$rel->referential_integrity) &&
    ($outer_joins_only || $with_objects{$arg}))
{
... use LEFT OUTER JOIN
}
else
{
.... use either an explicit JOIN (inner) or an implicit join
}

So, the rules surrounding the foreign key essentially mean that records
from table b are only meaningful if they reference table c, and as such,
any table b record requires a corresponding table c record.  Given the
NOT NULL constraints on the FKs in table b, this is entirely valid.

However, I believe the assumption is being misapplied in this particular
case, due to the fact that we're using table b in a with_objects list
rather than a require_objects list;  this is basically the same as
saying "give me table a stuff, and give me tables b and c if you got
'em."  In such a case, my table a records should come through whether or
not they have relations all the way out to table c via table b.
However, due to the behavior mentioned above, table c is included with a
simple join (meaning an inner join).  That certainly enforces the rule
that you only get table b records that are valid within our set of
assumptions, but it also means that we don't get any table a records
that do not have such table b records.

Would it not be better in this case for each relation in a join to
consider the other relation in that join and adjust the logic
appropriately?  In this example, table b has been added as a left outer
join because its in with_objects.  When looking at table c, we may
determine that the FK involved means that table c is effectively
"required" in order for table b's data to be valid; however, we should
consider that table b itself isn't required for this particularly query,
and therefore still use a left outer join for table c rather than an
inner join.

The data validity rules enforced in the current logic could still be
enforced through appropriate application of additional where clauses,
such that we only get records included table b data if such records also
include table c data:
SELECT
...
FROM a t1
LEFT OUTER JOIN b t2
    ON t2.a_id = t1.id
LEFT OUTER JOIN c t3
    ON t3.id = t2.c_id
WHERE
    (t2.id IS NULL OR t3.id IS NOT NULL)
    ...

We can work around this issue at the present through use of a "soft"
foreign key.  It seems preferable to me, however, that the query builder
construct the query in a manner more consistent with the meaning
expressed through with_objects.

I was about to dive into this and see if I could could up with a patch
that would do this, but I figured it would be better to correspond with
the list first and make sure I'm not missing something.  Am I? :)

Thanks in advance for any input, and for patiently wading through this
entire message.
- Ethan

-- 
Ethan Rowe
End Point Corporation
[EMAIL PROTECTED]



-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Rose-db-object mailing list
Rose-db-object@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rose-db-object

Reply via email to