cakephp icon indicating copy to clipboard operation
cakephp copied to clipboard

multiple matching or innerJoin calls drops dot notated association's conditions

Open rrd108 opened this issue 9 years ago • 16 comments

This is a (multiple allowed):

  • [x] bug

  • [ ] enhancement

  • [ ] feature-discussion (RFC)

  • CakePHP Version: 3.3.7

  • Platform and Target: Apache/2.4.18 (Ubuntu)

What you did

Authors hasMany SpecialTags Authors belongsToMany Tags SpecialTags belongsTo Tags

    $authorsTable = TableRegistry::get('Authors');
    $query = $authorsTable->find();
    $result = $query->matching('Tags', function ($q) {
            return $q->where(['Tags.id IN ' => [2]]);
        });

    //calling a second matching or innerJoin
    $result = $query->matching('SpecialTags.Tags', function ($q) {
            return $q->where(['Tags.id IN ' => [1, 3]]);
        });

Changing the order of matching calls won't help, same result, the conditions in the dot notated call is dropped.

What happened

The where condition of the second matching call is dropped. It is missing from the generated SQL. Even if you put a non-existent field name in where - there is no error.

What you expected to happen

The second matching's where conditions should be added to the generated SQL query.

rrd108 avatar Nov 05 '16 13:11 rrd108

What SQL query are you expecting to be generated? You have 2 joins to the tags table, the ORM is obviously preferring the first/shortest path to the association which is reasonable to me.

markstory avatar Nov 05 '16 13:11 markstory

I am expecting to have an inner join inside the inner join of specialtags. Or, (I guess would give the same results) if both where conditions whould go together to tag's inner join.

Anyway dropping a condition without any warning is hard to debug.

rrd108 avatar Nov 05 '16 13:11 rrd108

This is the expected behavior, although i understand it is surprising. Currently there is no detection of conflicting calls, and I agree that could be a good improvement

lorenzo avatar Nov 05 '16 14:11 lorenzo

@lorenzo if you think it is possible and give me some direction I would try to fix this.

rrd108 avatar Nov 05 '16 15:11 rrd108

Let try and see if I can come up with a plan for this

lorenzo avatar Nov 05 '16 17:11 lorenzo

@lorenzo any update on this? If you are waiting for me I would need some direction about where to dig into the code.

rrd108 avatar Nov 14 '16 10:11 rrd108

@rrd108 sorry, I was out during the week for a conference. If you feel brave, the place to look at is EagerLoader, probably around the normalize method, which is the one calculating the path to follow for loading the associations

lorenzo avatar Nov 15 '16 08:11 lorenzo

@lorenzo Today I spent a few hours on this. For me it seems that noramilze keep what we need here. _resolveJoins still have them, but I was not able to figure out what happens in that functions as it is a recursive and I guess my debugger run out of memory. So I am not closer at all, and do not really have an idea how to move forward. :-(

I think valueBinder is responsible for this behavior.

rrd108 avatar Nov 20 '16 14:11 rrd108

I'll try to work on this tomorrow

lorenzo avatar Nov 20 '16 19:11 lorenzo

I'm not sure there will be a fix though, maybe the best we can do is throw an exception or a warning

lorenzo avatar Nov 20 '16 19:11 lorenzo

I believe I'm having a similar issue as well with the ORM dropping associations. All my code is on the StackOverflow question. Let me know if a separate issue should be opened.

http://stackoverflow.com/questions/40978554/cakephp-3-matching-and-contain-not-returning-association

kyleweishaupt avatar Dec 06 '16 21:12 kyleweishaupt

@lorenzo What do you think we should do based on the open PR?

dereuromark avatar Dec 29 '17 14:12 dereuromark

@dereuromark what open PR?

lorenzo avatar Dec 30 '17 18:12 lorenzo

@lorenzo https://github.com/cakephp/cakephp/pull/9712

dereuromark avatar Jan 30 '18 19:01 dereuromark

Yeah, as insad before, this is the expected behavior, although it is entirely surprising. You cannot easily have 2 inner joins to the same table with the same alias, there is pretty much no workaround.

The only thing we could eventually do is throw an error

lorenzo avatar Jan 31 '18 10:01 lorenzo

It seems I found a workaround by putting the second matching into the first one. However did not test it yet...

$result = $query->matching('Tags', function ($q) {
    return $q->where(['Tags.id IN ' => [2]])
        ->matching('SpecialTags', function ($q) {
            return $q->where(['Tags.id IN ' => [1, 3]]);
        });
    });

rrd108 avatar Aug 04 '18 10:08 rrd108