Skip to content

PHPLIB-881: Consolidate validation of aggregation pipeline options #1078

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

Merged
merged 1 commit into from
Jun 14, 2023

Conversation

GromNaN
Copy link
Member

@GromNaN GromNaN commented May 23, 2023

Fix PHPLIB-881

Leverage is_pipeline to validate $pipeline argument and "pipeline" option. Since this function returns a boolean, it does not provide context about the error. This change allows to factorise the code and to go further in the validation, but the message in the exception is less precise.

@GromNaN GromNaN requested review from jmikola and alcaeus May 24, 2023 06:33
Copy link
Member

@alcaeus alcaeus left a comment

Choose a reason for hiding this comment

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

Suggested rewording the exception message for clarity, as we generally should refer to this as an "aggregation pipeline" as it is usually called in the documentation.

@@ -229,7 +229,7 @@ public function __construct(string $databaseName, string $collectionName, array
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][1]', $i, $type), $args[1], 'array or object');
}

if (! is_first_key_operator($args[1]) && ! is_pipeline($args[1])) {
if ($args[1] === [] || ! is_first_key_operator($args[1]) && ! is_pipeline($args[1])) {
Copy link
Member Author

Choose a reason for hiding this comment

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

I need to check the spec to see if an empty array is accepted in the following cases:

  • BulkWrite UPDATE_MANY and UPDATE_ONE
  • FindOneAndUpdate
  • ReplaceOne
  • Update, UpdateMany, UpdateOne

Copy link
Member

Choose a reason for hiding this comment

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

Outside of ReplaceOne and findOneAndReplace, an empty update array should be rejected, as it would entail a no-op on the server. In a replace operation, it would mean "replace the matched document with an empty document", which could be a valid use case (even though I fail to see how).

Replace currently allows an aggregation pipeline, but this will be removed in PHPLIB-1129.

Copy link
Member Author

Choose a reason for hiding this comment

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

So I'll change the behavior for ReplaceOne that is currently rejecting empty array.

Copy link
Member

Choose a reason for hiding this comment

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

Should be fine - just make sure it is covered by a test.

FWIW, the shell behaves the same way:

test> // Replace with empty replacement
test> db.test.replaceOne({_id: 1}, {})
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}
test> // Update with empty document
test> db.test.updateOne({_id: 1}, {})
MongoInvalidArgumentError: Update document requires atomic operators
test> // Update with empty pipeline
test> db.test.updateOne({_id: 1}, [])
MongoInvalidArgumentError: Update document requires atomic operators

Copy link
Member Author

Choose a reason for hiding this comment

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

@GromNaN GromNaN requested a review from alcaeus May 24, 2023 10:58
['y' => 1],
(object) ['y' => 1],
new BSONDocument(['y' => 1]),
]);
}

public function provideUpdateDocuments()
public function provideInvalidReplacementDocuments()
Copy link
Member

Choose a reason for hiding this comment

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

Note: this is going to conflict with #1077. The changes in that PR are more involved, so I'd suggest waiting on that to be merged.

Consideration of PackedArray instances for pipeline values is also going to impact this PR.

@jmikola
Copy link
Member

jmikola commented May 26, 2023

@GromNaN: #1077 has been merged but I'm still expecting some conflicts due to PHPLIB-1129. I also just realized that PHPLIB has historically prohibited empty update pipelines despite those being valid (DRIVERS-2638).

Please hold off on resuming this PR until I can sort that out next week.

@GromNaN GromNaN force-pushed the PHPLIB-881 branch 2 times, most recently from 124bb58 to 41aad07 Compare June 1, 2023 19:06
@GromNaN
Copy link
Member Author

GromNaN commented Jun 1, 2023

PR rebased.

Consideration of PackedArray instances for pipeline values is also going to impact this PR.

The dumb comparison $pipeline === [] is not possible with PackedArray. So I added an argument to is_pipeline to specify the return value in case of empty list. This also simplified conditions in existing if statements.

Empty pipelines are allowed

Reword "list of pipeline operations"

As used in the doc

Makes is_pipeline accept empty list

Keep forbidding empty replacement in ReplaceOne

Update psalm-baseline

Add argument to is_pipeline to set return value for empty pipeline

Necessary to handle non-array values
Copy link
Member

@alcaeus alcaeus left a comment

Choose a reason for hiding this comment

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

LGTM. While I'm not a fan of the comments indicating an option name, I'm fine with having them since we can't use named arguments for the purpose.

@GromNaN
Copy link
Member Author

GromNaN commented Jun 14, 2023

LGTM. While I'm not a fan of the comments indicating an option name, I'm fine with having them since we can't use named arguments for the purpose.

I copied the style introduced by @jmikola and discussed in review. Could be reverted.

@alcaeus
Copy link
Member

alcaeus commented Jun 14, 2023

I copied the style introduced by @jmikola and discussed in review. Could be reverted.

Ah, I missed that one. No worries then, perfectly fine with it 👍

@GromNaN GromNaN merged commit 8c999d1 into mongodb:master Jun 14, 2023
@GromNaN GromNaN deleted the PHPLIB-881 branch June 14, 2023 14:26
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