Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

whereHasMorph generates wrong sql in whereHas Callback #36536

Closed
Zepryit opened this issue Mar 10, 2021 · 7 comments
Closed

whereHasMorph generates wrong sql in whereHas Callback #36536

Zepryit opened this issue Mar 10, 2021 · 7 comments

Comments

@Zepryit
Copy link

Zepryit commented Mar 10, 2021

  • Laravel Version: 8.19.0
  • PHP Version: 7.4.2
  • Database Driver & Version: MariaDB 10.5.8

Description:

The use of whereHasMorph in a whereHas callback generates a wrong sql statements. A call to the whereHasMorph outside of a whereHas callback works fine.
The sql generated by the whereHas-whereHasMorph combination:

select * from `planning_contexts` where exists (
    select * from `planning_contexts` as `laravel_reserved_0` where `planning_contexts`.`context_id` = `laravel_reserved_0`.`context_id` and (
       (
            /* --- This is the wrong sql --- */
            `planning_contexts` as `laravel_reserved_0.plannable_type` = ? 
            /* ------------------------------ */
            and exists (
                select * from `versions` where `laravel_reserved_0`.`plannable_id` = `versions`.`id` and `published_at` = ?)
       )
   )
) order by `context_id` asc

Steps To Reproduce:

The PlanningContext class

class PlanningContext extends Model {
    /**
      * The relation which is used by the whereHas.
      * 
      * @return HasMany
      */
    public function relatedPlanningContexts(): HasMany {
        return $this->hasMany(PlanningContext::class, 'context_id', 'context_id');
    }

    /**
      * The realtion which is used by the whereHasMorph
      * 
      * @return MorphTo
      */
    public function plannable(): MorphTo {
        return $this->morphTo('plannable');
    }
}

The code which reproduces the error:

PlanningContext::whereHas('relatedPlanningContexts', function (Builder $query) {
    $query->whereHasMorph('plannable', [Version::class], function (Builder $q) {
        $q->where('published_at', Version::max('published_at'));
    });
})->orderBy('context_id', 'ASC')->paginate(100);
@taylorotwell
Copy link
Member

Feel free to PR a fix. I probably won't spend any time myself digging into this.

@taylorotwell
Copy link
Member

taylorotwell commented Mar 10, 2021

Also your query is a bit confusing - you have whereHasMorph('plannable') nested in the whereHas query callback but you have plannable listed on the PlanningContext model - so why is it nested within the whereHas?

@Zepryit
Copy link
Author

Zepryit commented Mar 10, 2021

The PlanningContext has a relation to itself by a context_id this defines an entry in a planning grid. And the polymorphic relation defines what entities are planned with each other.

E.g. I have one PlanningContext connected to a User, one to a Station, and one to a Version of the plan. These PlanningContexts are related by their context_id which means the User is planned at the Station in this Version of the plan.

When I want to show all entries of a specific Version, in this case the latest, i need to find all PlanningContexts with a connection to another PlanningContext which is connected to the specific Version.

I am also not sure if this is the best approach for my project. I am still researching.

I have already tried to find the issue but with no success yet. But i will give it another try in my free time.

@staudenmeir
Copy link
Contributor

We need to adjust $this->query->from.'.'.$relation->getMorphType() in:

$query->where($this->query->from.'.'.$relation->getMorphType(), '=', (new $type)->getMorphClass())

I see two options:

  • $this->qualifyColumn($relation->getMorphType())
  • last(preg_split('/\s+as\s+/i', $this->query->from)).'.'.$relation->getMorphType()

The first one would be more elegant, but I'm not sure if it works with all edge cases.

@driesvints
Copy link
Member

Anyone up for PR'ing the above?

taylorotwell pushed a commit that referenced this issue Mar 30, 2021
The use of whereHasMorph in a whereHas callback generates a wrong sql statements. Correction of this incorrectly constructed statement has been applied.
@selcukcukur
Copy link
Contributor

selcukcukur commented Mar 30, 2021

Fixed with pull request #36801 can be closed. @driesvints

@driesvints
Copy link
Member

@selcukcukur thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants