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

ENH Zero limit no results #10652

Merged
merged 3 commits into from
Jan 26, 2023

Conversation

maxime-rainville
Copy link
Contributor

Parent issue:

#10604

Comment on lines +185 to 187
if ($length < 0) {
throw new InvalidArgumentException("\$length can not be negative. $length was provided.");
}

if ($offset < 0) {
throw new InvalidArgumentException("\$offset can not be negative. $offset was provided.");
}
Copy link
Contributor Author

@maxime-rainville maxime-rainville Jan 18, 2023

Choose a reason for hiding this comment

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

We weren't validating for this before. If you give a negative length, methods like array slice will want to start from the end.

While this might make sense for an array, most DB don't think like that. Seems more logical to throw an exception.


if ($length === 0) {
// If we set the limit to 0, we return an empty list.
$list->items = [];
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you let array slice below do its thing, you'll end up with the same results. Seems clearer to do it explicitly.

Comment on lines 293 to 300
if ($length !== null && $length < 0) {
throw new InvalidArgumentException('$length can not be a negative value');
}

if ($offset < 0) {
throw new InvalidArgumentException('$offset can not be a negative value');
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Exceptions would be thrown any way by the queries below eventually. Seems better to just do it now.

*/
public function limit($limit, $offset = 0)
public function limit(?int $limit, int $offset = 0): static
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not necessary to meet the ACs, but seems logical to change this while we are at it.

@@ -249,7 +249,7 @@ public function setLimit($limit, $offset = 0)
throw new InvalidArgumentException("SQLSelect::setLimit() only takes positive values");
}

if (is_numeric($limit) && ($limit || $offset)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The second part of this IF statement would fail if 0,0 was provided. This would effectively prevent you from setting a zero limit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

setLimit() actually accept strings and array. This seems a bit weird but refactoring this is probably beyond the scope of this card.

@@ -117,34 +117,69 @@ function ($item) use (&$count, $test) {
$this->assertEquals($list->Count(), $count);
}

public function testLimit()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a bit weird how limited the test coverage was for such a critical method.

$check = $list->limit(false);
$this->assertEquals(3, $check->count());
$this->assertEquals(0, $check->count());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not done with this part yet.

*/
public function limit($limit, $offset = 0);
public function limit(?int $length, int $offset = 0): static;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've decided to rename the first parameter $length. My instinct is that this makes clearer that there's multiple possible parameters here.

$length = count($this->items ?? []);
if ($length === null) {
// If we unset the limit, we set the length to the size of the list. We still want the offset to be picked up
$length = sizeof($this->items);
Copy link
Member

Choose a reason for hiding this comment

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

What's the advantage of sizeof over count? count seems to be the more standard way to get the number of items in a Countable or array.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Apparently it's exactly the same thing. https://www.php.net/manual/en/function.sizeof.php

For some reason, I've always defaulted to sizeof. Don't have any preference either way.

Comment on lines 294 to 298
throw new InvalidArgumentException('$length can not be a negative value');
}

if ($offset < 0) {
throw new InvalidArgumentException('$offset can not be a negative value');
Copy link
Member

Choose a reason for hiding this comment

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

Make these the same as the text used for the ArrayList exceptions

*/
public function limit($limit, $offset = 0)
public function limit(?int $limit, int $offset = 0): static
{
$this->query->setLimit($limit, $offset);
Copy link
Member

Choose a reason for hiding this comment

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

No exceptions on this one?

Copy link
Contributor Author

@maxime-rainville maxime-rainville Jan 23, 2023

Choose a reason for hiding this comment

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

This method is really just an alias for calling $query->setLimit(). So it seems rational to just let setLimit do all the work.

@@ -249,7 +249,7 @@ public function setLimit($limit, $offset = 0)
throw new InvalidArgumentException("SQLSelect::setLimit() only takes positive values");
Copy link
Member

Choose a reason for hiding this comment

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

Make this the same as the other exceptions

Copy link
Contributor Author

Choose a reason for hiding this comment

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

SQLSelect::setLimit() does substantially different things than the other limit methods. It accepts all sort of weird values like arrays and strings that the other don't.

We could change this error message to something more specific ... but I think it needs to be different than the other methods.

*/
public function limit($limit, $offset = 0);
public function limit(?int $length, int $offset = 0): Limitable;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to return a static here ... but list decorator doesn't actually return a version of itself, so I couldn't do that.

@maxime-rainville
Copy link
Contributor Author

Ran the full sink against my PR branch and got all greens: https://github.com/maxime-rainville/recipe-kitchen-sink/actions/runs/4002316914

@@ -16,21 +16,16 @@ abstract class ListDecorator extends ViewableData implements SS_List, Sortable,
/**
* @var SS_List
*/
protected $list;
protected SS_List&Sortable&Filterable&Limitable $list;
Copy link
Contributor Author

@maxime-rainville maxime-rainville Jan 25, 2023

Choose a reason for hiding this comment

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

Basically, every method on the class assumes that we will return a List that implements all these interfaces.

@maxime-rainville maxime-rainville marked this pull request as ready for review January 25, 2023 04:31
@maxime-rainville
Copy link
Contributor Author

Added a test for the tweak to SQLSelect ... I also got a for of the sink running all the CI to make sure no other module needs updating https://github.com/maxime-rainville/recipe-kitchen-sink/actions/runs/4002850477

src/ORM/DataList.php Show resolved Hide resolved
src/ORM/ArrayList.php Show resolved Hide resolved
tests/php/ORM/SQLSelectTest.php Outdated Show resolved Hide resolved
src/ORM/DataList.php Show resolved Hide resolved
tests/php/ORM/SQLSelectTest.php Outdated Show resolved Hide resolved
@maxime-rainville
Copy link
Contributor Author

All feedback answered.

Copy link
Contributor

@sabina-talipova sabina-talipova left a comment

Choose a reason for hiding this comment

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

Looks good for me

@sabina-talipova
Copy link
Contributor

Passed tests locally. Approved and merged.

@sabina-talipova sabina-talipova merged commit 0fee1aa into silverstripe:5 Jan 26, 2023
@sabina-talipova sabina-talipova deleted the pulls/5/limit-0 branch January 26, 2023 21:52
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