Skip to content

[5.5] fix a bug where model's delete method won't work if withCount is not empty. - #22239

Closed
abdumu wants to merge 4 commits into
laravel:5.5from
abdumu:withcount_delete_fix
Closed

[5.5] fix a bug where model's delete method won't work if withCount is not empty.#22239
abdumu wants to merge 4 commits into
laravel:5.5from
abdumu:withcount_delete_fix

Conversation

@abdumu

@abdumu abdumu commented Nov 28, 2017

Copy link
Copy Markdown
Contributor

This fixes the bug that makes delete query receive two params instead of one if withCount array is not empty.

Before:

array:2 [▼
  0 => array:3 [▼
    "query" => "select `posts`.*, (select count(*) from `comments` where `posts`.`id` = `comments`.`commentable_id` and `comments`.`commentable_type` = ?) as `comments_count` f ▶"
    "bindings" => array:2 [▼
      0 => "App\Post"
      1 => "14"
    ]
    "time" => 6.3
  ]
  1 => array:3 [▼
    "query" => "delete from `posts` where `id` = ?"
    "bindings" => array:1 [▼
      0 => "App\Post"
      1 => "14"
    ]
    "time" => 0.84
  ]
]

After:

array:2 [▼
  0 => array:3 [▼
    "query" => "select `posts`.*, (select count(*) from `comments` where `posts`.`id` = `comments`.`commentable_id` and `comments`.`commentable_type` = ?) as `comments_count` f ▶"
    "bindings" => array:2 [▼
      0 => "App\Post"
      1 => "14"
    ]
    "time" => 6.3
  ]
  1 => array:3 [▼
    "query" => "delete from `posts` where `id` = ?"
    "bindings" => array:1 [▼
     0 => "14"
    ]
    "time" => 0.84
  ]
]

@Dylan-DPC-zz

Copy link
Copy Markdown

Can you write a test with this testcase ?

@abdumu

abdumu commented Nov 28, 2017

Copy link
Copy Markdown
Contributor Author

I added a test.

This is the PR when withCount was introduced #19154

@taylorotwell

Copy link
Copy Markdown
Member

Eh, I don't like adding this seemingly random parameter to newQueryWithoutScopes. @themsaid do you have a more elegant solution?

@themsaid

Copy link
Copy Markdown
Member

@taylorotwell the new approach he took is much cleaner, it's the same approach we take while preparing the update query.

@taylorotwell

Copy link
Copy Markdown
Member

How does this affect MySQL DELETE statements that use a join: https://dev.mysql.com/doc/refman/5.7/en/delete.html

See "Multi Table Deletes".

@abdumu

abdumu commented Nov 29, 2017

Copy link
Copy Markdown
Contributor Author

Is it different than the test 'testDeleteWithJoinMethod' that is already written in DatabaseQueryBuilderTest.php ?

@themsaid

Copy link
Copy Markdown
Member

@abdumu In the current code you remove the join bindings from the query, what happens if there's a delete query that uses joins? With this code it'll fail since the join bindings were removed.

@abdumu

abdumu commented Nov 29, 2017

Copy link
Copy Markdown
Contributor Author

I didn't remove join bindings.

@themsaid

Copy link
Copy Markdown
Member

@abdumu

abdumu commented Nov 29, 2017

Copy link
Copy Markdown
Contributor Author

Check https://github.com/laravel/framework/pull/22239/files#diff-bf9c2a600451a26e98eba7874fb841caR775

This is the same way you did it in prepareBindingsForUpdate, to make join bindings first.

@themsaid

Copy link
Copy Markdown
Member

@abdumu yes and I believe it's wrong too, we'll need some integration tests similar to Illuminate\Tests\Integration\Database\EloquentWithCountTest to make sure these cases work.

  • Update statement withCount that has joins.
  • Delete statement withCount that has joins.

Can you do that?

@abdumu

abdumu commented Nov 29, 2017

Copy link
Copy Markdown
Contributor Author

I just found out that Grammar.php/compileDelete query doesn't respect joins and Laravel send joins where bindings to it. That is not an issue if MySQL is the engine because MySqlGrammar.php/compileDelete respect joins.

I'm sorry I'm not sure I can test multiple engines with different approach. but I'll keep digging.

@tillkruss tillkruss changed the title fix a bug where model's delete method won't work if withCount is not empty. [5.5] fix a bug where model's delete method won't work if withCount is not empty. Nov 30, 2017
@taylorotwell

Copy link
Copy Markdown
Member

Where are we with this? @themsaid?

@themsaid

themsaid commented Dec 2, 2017

Copy link
Copy Markdown
Member

@taylorotwell I've tested it for MySQL and it works but I'm not sure about Postgres and sql server, they seems to have a unique syntax for delete statements with joins, MySQL needs the join bindings to be sorted first, postgres seems to require the where bindings first and then join bindings, and also seems that postgres doesn't remove select bindings.

tl;dr
The PR is unmergable without someone who can test it on Postgres and sql server, sorry I don't have large experience in either.

@themsaid

themsaid commented Dec 2, 2017

Copy link
Copy Markdown
Member

A safe thing we could do is to return the exact input in Grammar:prepareBindingsForDelete and then in MySQL's Grammar:prepareBindingsForDelete we do the changes, that way we're sure rest of engines will receive the same input as before.

@themsaid

themsaid commented Dec 2, 2017

Copy link
Copy Markdown
Member

@abdumu can you check my last comment regarding the method implementation in different grammars?

@abdumu

abdumu commented Dec 2, 2017

Copy link
Copy Markdown
Contributor Author

withCount is meant for select queries, having counts in delete, update and then trying to remove the counts is absurd !

Since we are using newQueryWithoutScopes in performDeleteOnModel, save, ...
I think the right way to do it, is by setting $this->withCount to [], and re-assign it to the previous value after calling newQueryWithoutScopes.

Also, Sqlite Grammar is ignoring joins completely so no point of the integration tests ! (I might do some work later on this in another PR)

@themsaid

themsaid commented Dec 2, 2017

Copy link
Copy Markdown
Member

Closing this since it's a possibly breaking change, please re-submit on master so we can prevent breaking other grammars.

@themsaid themsaid closed this Dec 2, 2017
@abdumu
abdumu deleted the withcount_delete_fix branch December 2, 2017 18:57
@themsaid

themsaid commented Dec 2, 2017

Copy link
Copy Markdown
Member

I've opened a PR with my suggested change in #22285

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants