Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@niklasj
Copy link
Contributor

@niklasj niklasj commented Feb 2, 2022

Make sure that the values returned from find() and find_one() when a
projection is specified don't share any references to the actual db
documents.

Fixes #728

@codecov
Copy link

codecov bot commented Feb 2, 2022

Codecov Report

Merging #753 (51d259f) into develop (a2ef88a) will increase coverage by 0.06%.
The diff coverage is 100.00%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop     #753      +/-   ##
===========================================
+ Coverage    95.08%   95.14%   +0.06%     
===========================================
  Files           19       19              
  Lines         3743     3731      -12     
===========================================
- Hits          3559     3550       -9     
+ Misses         184      181       -3     
Impacted Files Coverage Δ
mongomock/collection.py 92.48% <100.00%> (+0.14%) ⬆️
mongomock/filtering.py 99.01% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a2ef88a...51d259f. Read the comment docs.

@niklasj
Copy link
Contributor Author

niklasj commented Feb 2, 2022

I'm not sure if this needs a test to compare it against the real MongoDB engine or not. But I'll add one if you would like it.

Copy link
Member

@pcorpet pcorpet left a comment

Choose a reason for hiding this comment

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

Thanks for the PR. I don't think we need a test in test__mongomock for this one, so let's keep it like this.

else:
doc_copy = _project_by_spec(
doc, _combine_projection_spec(fields),
self._copy_field(doc, container),
Copy link
Member

Choose a reason for hiding this comment

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

This does the job but in many cases some values will be copied several times. I suggest that you update the _combine_projection_spec instead and add a copy in the places where the are no copies yet (doc_copy[key] = doc[key] and doc_copy[key] = val)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah… I think I see what you mean – if fields are excluded (e.g.find_one(projection={'field': 0})) or nested fields are used (e.g. find_one(projection={'field.subfield': 1})), then _project_by_spec would copy the values a second time.

I'll update the pull request accordingly, but I'm wondering a bit about the container parameter. As far as I can tell it's never anything but dict, so I'm wondering what its purpose is and if it would be OK to just copy.deepcopy() the values?

Copy link
Member

Choose a reason for hiding this comment

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

The container parameter was meant to use the implementation of the codec option document_class, if it's not too much trouble I'd like to keep it as such for now.

Make sure that the values returned from find() and find_one() when a
projection is specified don't share any references to the actual db
documents.

Fixes mongomock#728
Copy only included fields, and only do it once.
@niklasj niklasj force-pushed the find-projection-independency branch from fad56a5 to 87671fd Compare February 9, 2022 07:08
elif isinstance(val, dict):
doc_copy[key] = _project_by_spec(val, spec, is_include, container)
elif (is_include and spec is not NOTHING) or (not is_include and spec is NOTHING):
doc_copy[key] = copy.deepcopy(val)
Copy link
Member

Choose a reason for hiding this comment

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

Let's add at least a comment that this should use container if it's a dict-like object or may contain dict-like objects.

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 changed it to use _copy_field instead now.

@niklasj niklasj requested a review from pcorpet February 10, 2022 08:18
@pcorpet pcorpet merged commit 5e38e97 into mongomock:develop Feb 10, 2022
@pcorpet
Copy link
Member

pcorpet commented Feb 10, 2022

Thanks or the change

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.

Changing find_one() result unexpectedly changes value stored in the database

2 participants