Skip to content
This repository has been archived by the owner on Aug 22, 2023. It is now read-only.

PHPORM-49 Implement Query\Builder::whereNot by encapsulating into $not #13

Merged
merged 6 commits into from
Jul 19, 2023

Conversation

GromNaN
Copy link
Owner

@GromNaN GromNaN commented Jul 13, 2023

Fix PHPORM-49

Query\Builder::whereNot was simply ignoring the "not" and breaking the built query.

@GromNaN GromNaN changed the title PHPORM-49 Implement whereNot by encapsulating into $not` PHPORM-49 Implement Query\Builder::whereNot by encapsulating into $not Jul 13, 2023
tests/Query/BuilderTest.php Outdated Show resolved Hide resolved
@GromNaN GromNaN force-pushed the PHPORM-49 branch 2 times, most recently from 9ee1e65 to bf569c5 Compare July 13, 2023 12:09
@GromNaN GromNaN requested review from alcaeus and jmikola July 13, 2023 12:09
&& str_starts_with($where['boolean'], 'and')
&& str_starts_with($wheres[$i + 1]['boolean'], 'or')
) {
$where['boolean'] = 'or'.(str_ends_with($where['boolean'], 'not') ? ' not' : '');
Copy link
Owner Author

@GromNaN GromNaN Jul 13, 2023

Choose a reason for hiding this comment

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

$where['boolean'] can be and, or, and not or or not. It is used as-this into SQL queries. I tried several implementations to split into vars that are easier to use later, but using str_ functions is the simplest.

Copy link
Collaborator

@jmikola jmikola left a comment

Choose a reason for hiding this comment

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

Some questions and suggestions, but the tests look correct.

Even thought it's a bug fix, this change looks like it warrants special documentation to keep users informed. Should we start a Markdown file in the project (perhaps an UPGRADING-X.Y.md) to demonstrate how query builder methods are changing? That could just show what a method previously built and what it would now.

tests/Query/BuilderTest.php Show resolved Hide resolved
[], // options
]],
fn (Builder $builder) => $builder
->whereNot([['foo', 1], ['bar', '<', 2]]),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should both elements be a three-element array with an operator, or was it intentional to only do so for the second?

Copy link
Owner Author

@GromNaN GromNaN Jul 19, 2023

Choose a reason for hiding this comment

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

That's intentional, arrays are arguments to call Query\Builder::where(...$args).
https://github.com/GromNaN/laravel-mongodb-private/blob/cf103ba0ddc8a4ca601aab338e8298e0fdbff018/src/Query/Builder.php#L943

Laravel Eloquent has this feature.

tests/Query/BuilderTest.php Show resolved Hide resolved
tests/Query/BuilderTest.php Outdated Show resolved Hide resolved
tests/Query/BuilderTest.php Outdated Show resolved Hide resolved
tests/Query/BuilderTest.php Outdated Show resolved Hide resolved
tests/Query/BuilderTest.php Outdated Show resolved Hide resolved
fn (Builder $builder) => $builder->where(['foo' => 1, 'bar' => 2]),
];

yield 'nested orWhere and where' => [
Copy link
Collaborator

Choose a reason for hiding this comment

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

"nested orWhere and where" seems a bit simplistic given the complexity of this query.

Is it relevant that you're testing orWhere with a callable? Is the combination of where and whereNot relevant? I'm not sure how this compares to the where orWhereNot (per my suggested name below) test later in the file.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I removed this test and added whereNot orWhere to ensure the not it kept when the 1st condition get the $or logical operator from the 2nd.

@GromNaN GromNaN requested a review from jmikola July 19, 2023 09:14
Copy link
Collaborator

@jmikola jmikola left a comment

Choose a reason for hiding this comment

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

Some comments to follow-up on with a separate ticket, but changes here LGTM.

Comment on lines +89 to +90
->whereNot('name', 'foo')
->whereNot('name', '<>', 'bar'),
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is likely beyond the scope of this PR, but there's room for improvement here. Rather than unconditionally wrap the query with $not, we could just use a more appropriate operator. For instance:

  • where() assumes an equality match, so whereNot() could use $ne instead of a direct value match (as we have here) or $eq.
  • whereNot() with a <> operator could utilize $eq or a direct value match instead.

If you agree, perhaps we can track this in a new PHPORM ticket. I wouldn't limit the query optimization to $not. It should probably be a much larger task to scope out for the entire query builder.

]],
[], // options
]],
fn (Builder $builder) => $builder->where(['foo' => 1, 'bar' => 2]),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Beyond the scope of this PR I'm sure, but I don't understand why this results in an $and with separate conditions instead of ['find' => ['foo' => 1, 'bar' => 2]]. Something else to address in query builder optimization follow-up work I suppose.

[], // options
]],
fn (Builder $builder) => $builder
->whereNot(['foo' => 1, 'bar' => 2]),
Copy link
Collaborator

Choose a reason for hiding this comment

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

This also relates to my earlier comment about query optimization.

@GromNaN GromNaN merged commit 9d9c7c8 into master Jul 19, 2023
18 checks passed
@GromNaN GromNaN deleted the PHPORM-49 branch July 19, 2023 20:12
GromNaN added a commit that referenced this pull request Jul 19, 2023
…$not` (#13)

`Query\Builder::whereNot` was simply ignoring the "not" and breaking the built query.
GromNaN added a commit that referenced this pull request Jul 19, 2023
…$not` (#13)

`Query\Builder::whereNot` was simply ignoring the "not" and breaking the built query.
GromNaN added a commit that referenced this pull request Jul 20, 2023
…$not` (#13) (#15)

`Query\Builder::whereNot` was simply ignoring the "not" and breaking the built query.
GromNaN added a commit that referenced this pull request Aug 22, 2023
…$not` (#13)

`Query\Builder::whereNot` was simply ignoring the "not" and breaking the built query.
GromNaN added a commit that referenced this pull request Aug 22, 2023
…$not` (#13) (#15)

`Query\Builder::whereNot` was simply ignoring the "not" and breaking the built query.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants