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

#873 | implement delete with join #4568

Merged
merged 1 commit into from Jul 13, 2021

Conversation

Egor-Koldasov
Copy link
Contributor

Fix for the issue #873
The issue is that joins are not included in delete queries.
Examples can be found in tests: https://github.com/knex/knex/compare/master...Egor-Koldasov:fix/873-delete-join?expand=1#diff-9a54bb8c91fbb672179c076a18af9db40b73bc5c4a3e3ea7cc89c48ea8ebeadfR9944

Notes on the solution:

  1. Solution does not include the ability to delete multiple tables. To me, it is not clear, how the interface should be expanded to include this option. It would be great to have a recommendation from collaborators: Is it impossible to 'delete join'? #873 (comment)
    It does solve other issues, allowing to delete values from a table by filtering values from another joined table.
    It also helps with unexpected queries and potential data loss mentioned here: Is it impossible to 'delete join'? #873 (comment)

  2. Postgres, SQLite and Oracle do not support joins on delete. I did not include any custom error throws for them, instead, I allowed the query to build the same way and let the database report the error. Tests for error are included.

  3. The project has a linter added to the commit hook. It updated the whole file: https://github.com/knex/knex/compare/master...Egor-Koldasov:fix/873-delete-join?expand=1#diff-9a54bb8c91fbb672179c076a18af9db40b73bc5c4a3e3ea7cc89c48ea8ebeadf
    I'm not sure why previous commits have not done this, since it is automatic.

  4. I'm having issues with successfully running 1 test: https://github.com/knex/knex/blob/master/test/integration/query/selects.js#L1361
    The timeout error is not being caught properly leading to a general "Timeout of 5000ms exceeded." error.
    It is not related to this update, but it's better to let know.

Thanks.

.join('accounts', 'accounts.id', 'test_table_two.account_id')
.where({ 'accounts.email': 'test3@example.com' })
.del();
if (isSQLite(knex) || isPostgreSQL(knex) || isOracle(knex)) {
Copy link
Collaborator

@kibertoad kibertoad Jul 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you see downsides of using this approach for PostgreSQL - https://www.postgresqltutorial.com/postgresql-delete-join/?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kibertoad I did not think about it since it has a different syntax.
The best solution for PostgreSQL I think would be to add direct support for USING syntax like a .using method, it can use the same interface with the current .join.
Overall, internally transforming from .join might be convenient and helpful too. Among downsides, maybe a small confusion from query transformation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair. Converting joins to non-joins is likely to be confusing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case it would seem to be quite trivial crossdb compatibility thing to implement... though, maybe native syntax should be allowed too.

Also tests for error cases where people tries to create .join queries for unsupported databases seem to be missing.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Egor-Koldasov Could you add these in a follow-up PR?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OlivierCavadenti Delete join support with USING syntax for PG at this point is probably the largest gap in functionality still missing for 1.0.0. If you'll have some spare time, any chance you could take a look at it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kibertoad yeah I can work on it soon. As I understand, and to be sure, we go on a syntax from :

knex
	.select('xyz')
	.from('my_table')
	.leftJoin('users', 'users.user_id', 'my_table.user_id')
        .where('my_table.criteria', '<', 10)
	.delete();

to in PG (no hidden converting left join to using ?):

knex
	.select('xyz')
	.from('my_table')
	.using('users')
        .where('my_table.criteria', '<', 10)
        .andWhere('users.user_id', 'my_table.user_id')
	.delete(); 

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, exactly!

@kibertoad
Copy link
Collaborator

I'm having issues with successfully running 1 test: https://github.com/knex/knex/blob/master/test/integration/query/selects.js#L1361
The timeout error is not being caught properly leading to a general "Timeout of 5000ms exceeded." error.
It is not related to this update, but it's better to let know.

This is a known flaky test, feel free to ignore.

@kibertoad kibertoad merged commit c335fda into knex:master Jul 13, 2021
@kibertoad
Copy link
Collaborator

Thanks!

bindings: ['mock@test.com'],
},
pg: {
sql: 'delete "users" from "users" inner join "photos" on "photos"."id" = "users"."id" where "user"."email" = ?',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this valid SQL or just generates error from database? If feature is not supported by database, knex should probably throw an error and tell about it or otherwise we will get bug reports about this feature not working.

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.

None yet

4 participants