Skip to content

PHPLIB-1144: Add unit tests on Explainable::getCommandDocument() #1105

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 6 commits into from
Jun 19, 2023

Conversation

GromNaN
Copy link
Member

@GromNaN GromNaN commented Jun 14, 2023

Fix PHPLIB-1144

  • Add let and comment options to explain delete.
  • Remove explain option for Aggregate, it is incompatible with the explain command.

Adding a unit test will full options for each implementation of Explainable::getCommandDocument:

  • Count
  • Delete
  • DeleteMany covered by Delete
  • DeleteOne covered by Delete
  • Distinct
  • EstimatedDocumentCount covered by Count
  • Find
  • FindAndModify
  • FindOne covered by Find
  • FindOneAndDelete ✅ + covered by FindAndModify
  • FindOneAndReplace ✅ + covered by FindAndModify
  • FindOneAndUpdate ✅ + covered by FindAndModify
  • Update
  • UpdateMany covered by Update
  • UpdateOne covered by Update

These tests allow us to review exactly which options are sent to the explain command.

The comparison of ReadConcern values will become stronger with PHPC-2234.

@GromNaN GromNaN changed the title PHPLIB-1144: Add unit tests on Explainable::getCommandDocument PHPLIB-1144: Add unit tests on Explainable::getCommandDocument() Jun 14, 2023
@GromNaN GromNaN requested a review from jmikola June 14, 2023 13:26
@GromNaN GromNaN marked this pull request as ready for review June 14, 2023 13:26
'noCursorTimeout' => true,
'oplogReplay' => true,
'projection' => ['_id' => 0],
'readConcern' => new ReadConcern(ReadConcern::LOCAL),
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 know that this is not an effective comparison of the readConcern value, at least it asserts the readConcern option is sent. The assertion will be stronger once PHPC-2234 is implemented.

Copy link
Member

Choose a reason for hiding this comment

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

I suppose it's not worth adding a @todo comment here since the code won't need to be changed in PHPLIB. This is worth calling out in the commit message, though (with a reference to PHPC-2234).

@GromNaN GromNaN force-pushed the PHPLIB-1144 branch 2 times, most recently from 7d9ef90 to 1714264 Compare June 15, 2023 12:58
'projection' => ['_id' => 0],
'sort' => ['x' => 1],
'let' => ['a' => 3],
'typeMap' => ['root' => 'array'],
Copy link
Member

Choose a reason for hiding this comment

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

I suggest adding a comment before any ignored options.

'noCursorTimeout' => true,
'oplogReplay' => true,
'projection' => ['_id' => 0],
'readConcern' => new ReadConcern(ReadConcern::LOCAL),
Copy link
Member

Choose a reason for hiding this comment

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

I suppose it's not worth adding a @todo comment here since the code won't need to be changed in PHPLIB. This is worth calling out in the commit message, though (with a reference to PHPC-2234).

@GromNaN GromNaN force-pushed the PHPLIB-1144 branch 2 times, most recently from 9960219 to e370122 Compare June 16, 2023 13:28
@@ -300,6 +300,10 @@ public function getCommandDocument()
{
$cmd = $this->createCommandDocument();

// The 'explain' option is incompatible with the explain command
unset($cmd['explain']);
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 get the following error if the option explain is set, even if it's false.

MongoDB\Driver\Exception\CommandException: The 'explain' option is illegal when a explain verbosity is also provided

Copy link
Member

@jmikola jmikola Jun 16, 2023

Choose a reason for hiding this comment

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

I'm OK relying on the server to raise an error here if you'd like to remove this.

I'd argue this is fundamentally different from intentionally omitting writeConcern (PHPLIB-802) because that option is easily inherited from a parent context.

If a user encounters the error you highlighted above, it's because they've explicitly crafted an Aggregate operation with an explain option, and then decided to pass that to Collection::explain().

'filter' => (object) ['x' => 1],
'allowDiskUse' => true,
'allowPartialResults' => true,
'batchSize' => 123,
Copy link
Member Author

Choose a reason for hiding this comment

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

The batchSize seems to be useless for an explain. It is not supported by the aggregate command with explain option:

// Explain does not use a cursor
if ($this->isExplain) {
$options['useCursor'] = false;
unset($options['batchSize']);
}

Copy link
Member

Choose a reason for hiding this comment

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

The batchSize seems to be useless for an explain

I imagine so, but I don't think there's any reason for PHPLIB to care about that. We can rely on the server to ignore it or raise an error. I wouldn't expect an error (not going to bother testing myself), but if so the user could always revise their operation options.

The case for unsetting batchSize when using the explain option with aggregate is different. That logic has nothing to do with it being relevant/supported when explaining a pipeline, but rather the fact that aggregate with explain: true returns a single document. The batchSize option is only relevant if aggregate yields a cursor.

Copy link
Member

@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.

LGTM with at least the Psalm error resolved.

I'll defer to you on the other suggested changes.

'readConcern' => new ReadConcern(ReadConcern::LOCAL),
'useCursor' => true,
// Intentionally omitted options
'explain' => true,
Copy link
Member

Choose a reason for hiding this comment

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

As mentioned in #1105 (comment), I think it makes sense to include this and allow the server to raise an error.

If you agree, then I'd suggesting moving this above // Intentionally omitted options and under a comment noting that the explain that is rejected but we don't intentionally exclude it.

If you don't agree, then OK to keep this as-is.

$cmd = ['delete' => $this->collectionName, 'deletes' => [['q' => $this->filter] + $this->createDeleteOptions()]];

if (isset($this->options['comment'])) {
$cmd['comment'] = $this->options['comment'];
Copy link
Member

Choose a reason for hiding this comment

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

Note Psalm's MixedAssignment error. You may need an annotation to note that comment is actually mixed (any BSON type is supported).

Alternatively, you could just add this to the baseline file. We already have a number suppressions for MixedAssignment on $cmd['comment'].

@@ -353,6 +338,11 @@ private function createCommandDocument(): array
return $cmd;
}

// Read concern can change the query plan
if (isset($this->options['readConcern'])) {
Copy link
Member

Choose a reason for hiding this comment

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

I think this conditional can be removed.

createQueryOptions() actually includes the readConcern option, so it will already be added by the final $cmd + $options union in the return statement. This is because the readConcern option is passed to the Query constructor instead of Server::executeQuery() (as it might be for executeReadCommand() in other operations).

Hypothetically, if that wasn't the case, the position of this conditional would still be problematic due to the early return above if createQueryOptions() returns an empty array. The edge case would be constructing Find with only a readConcern option.

While writing this, I realized the docs regarding read concern inheritance for queries is not very clear. Opened PHPC-2249 to improve that.

GromNaN added 6 commits June 19, 2023 09:43
Remove private function createCommandDocument introduced by c7b2b03 and used only for the explain command.
Separate Intentionally omitted option
The 'explain' option is illegal when a explain verbosity is also provided
@GromNaN
Copy link
Member Author

GromNaN commented Jun 19, 2023

CS and Psalm checks OK. The failing tests are unrelated, due to mongodb/mongo-php-driver@358fd2f

@alcaeus
Copy link
Member

alcaeus commented Jun 19, 2023

Test failures are unrelated.

@alcaeus alcaeus merged commit 53052b6 into mongodb:master Jun 19, 2023
@GromNaN GromNaN deleted the PHPLIB-1144 branch June 19, 2023 08:14
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