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

Add EXISTS/NOT EXISTS support #94

Closed
wants to merge 2 commits into from

Conversation

mzealey
Copy link

@mzealey mzealey commented Dec 29, 2018

Per the POD this adds $rs->exists( $subq, { join cond } ) and ->not_exists(...) support

@coveralls
Copy link

coveralls commented Dec 29, 2018

Coverage Status

Coverage increased (+0.02%) to 98.693% when pulling 1254666 on mzealey:add-exists-subquery into ba9ab1b on frioux:master.

@frioux
Copy link
Owner

frioux commented Dec 29, 2018

@mzealey
Copy link
Author

mzealey commented Dec 29, 2018 via email

@frioux
Copy link
Owner

frioux commented Dec 29, 2018

Sure, you can do multi-column relationships in DBIC; here's an example (using ::Candy and ::DWIM to shorten the definition:)

belongs_to alarm_channel => '::AlarmChannel', {
   'foreign.user'       => 'self.user',
   'foreign.site'       => 'self.serial',
   'foreign.alarm'      => 'self.alarm',
   'foreign.alarmstate' => 'self.alarmstate',
};

@mzealey
Copy link
Author

mzealey commented Dec 29, 2018

@frioux Sure you can do joins like that. But lets say I want to search for items which dont't have a particular tag

SELECT *
FROM items
WHERE NOT EXISTS (SELECT 1 FROM item_tags WHERE items.id = item_tags.item_id AND some other criteria LIMIT 1)

I could do this as a left join checking for null but a) that is often much more intensive on the DB side (certainly in MySQL it can't optimize so well) and b) returns all the joined rows for items which have multiple tags which would later need filtering. I could also do this as corrolated with count and a having but again the correct way (and one which database can optimize much more simply) is to do the (NOT) EXISTS filters. If you have a join in the query the (NOT) EXISTS also allows you to reference multiple tables as well which is very powerful.

@frioux
Copy link
Owner

frioux commented Dec 29, 2018

Sorry I should have given a more complete example; the following should do what you just said:

$rs->search({
   -not_exists => $rs->correlate('item_tags')
      ->search({ some other criteria }, { rows => 1 })->as_query
 })

Honestly I'm ok with your PR on the face of it, I just think it reimplements some stuff that is already implemented; Just trying to make sure I'm not missing something.

@mzealey
Copy link
Author

mzealey commented Dec 29, 2018

@frioux OK I see what you mean now. I wasn't aware that could be done (both the corrolate and the -exists) and I can't see it documented anywhere as such - perhaps you could add exists/not exists to a cookbook somewhere so it is more obvious when searching? Only advantage that my code brings is that you can do dynamic joins but I'm sure there are other ways to do that and generally you shouldn't be doing that within dbic.

@frioux
Copy link
Owner

frioux commented Dec 29, 2018

Yeah honestly I was scouring the docs to link you to them and couldn't find anything. I fully agree that it should be documented and found.

I actually think dynamic joins are really useful! When I was trying to find examples of where I'd used -exists I found dynamic joins in my own code because it explicitly had no relationships because it was an initial migration.

Here's an idea: update your docs (there are some parts that are no longer correct, like the alias thing) and add some explanations of -exists and -not_exists; even if we get a patch into the cookbook, more examples in relevant places tend to be useful.

@mzealey
Copy link
Author

mzealey commented Dec 31, 2018

Would you be up for me writing something like ResultSet/Exists.pod based around the correlate functionality so people searching can find it more easily?

@frioux
Copy link
Owner

frioux commented Dec 31, 2018

Sure!

@frioux frioux closed this Jun 13, 2020
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.

3 participants