-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Select and Exclude queries do not properly digest JSON arrays #7245
Comments
@mtrezza I'm pasting your comment from the PR below to respond to:
Can you link to the fix you made? Without seeing the code, I'm assuming it may fall into my comments below (originally from the PR):
The current (before the PR) allowed a dev to pass |
Sure, it was #7161: Lines 103 to 106 in cac6951
It has a use case if you think about conditionally adding keys to an array:
The alternative is adding additional logic like:
|
If I'm understanding your fix correctly, it seems like there may have been a problem because If this is true, it seems like the change I added won't cause any issues with your fix, but I'm guessing |
I'll note, that if we decide to "keep" the parse-server/src/Routers/ClassesRouter.js Lines 211 to 213 in 5640cd5
But, as I mentioned before, I currently don't think that functionality should be in |
@mtrezza thinking about it more, I take back some of my previous comments. I didn't see the PR for your change (so I don't know the original code), but looking at the code snippet you sent, your change is probably why
will probably bring it back, but I still don't think it should be there |
Would it be beneficial to change that fix? It actually fixed a change introduced in MongoDB 4.4 - since we are now also CI testing against that version, we should see if anything breaks. I think if possible we should continue to allow |
Maybe, can you post the link to your PR that made the change? What your thoughts on about keeping/removing the functionality in select? Also, if anyone else has thoughts about it. |
I can understand the reasoning for this... The counter would be then we are continuing to leave something in that shouldn't be there, enabling new devs to use it, increasing the dependence on something that probably shouldn't have been there in the first place Basically the longer we leave it in, the harder it will be to remove in the future... Though, it's not something serious, so leaving it in may not be that big of a deal, assuming it's easy to add the functionality back to my fix |
I found the PR where your change occurred #7161. I tested with fix I have with/without it as well as some other combinations with the code block below, but none of them brought back the
if (body.keys && (typeof body.keys === 'string' || typeof body.keys === 'object')) {
options.keys = body.keys;
} So if the |
To keep the functionality, the latest commit on the PR has the changes to allow if (body.keys || body.keys === '') {
options.keys = String(body.keys);
} |
What shouldn't it? I think I missed the argument why this should be removed, can you explain again? |
My argument was here:
If you all think it should remain, it doesn't really bother me as it not something I will end up using. It just seems like it should be an exclude. My reasoning is what happens when you use If you all agree with my logic, but decide to keep it, then what I said earlier may be relevant:
I updated the PR to work with |
For clarity, I want to emphasize there are two topics here:
|
Let's see...
To me it makes sense semantically, I read it as "select none". It basically overrides the default behavior where all fields are selected and returned. However, the actual justification lies in examining it as member of logical extrema:
The I think we should make sure that all logical extrema yield correct results and make sure there are tests for each. What never stops to confuse me is that |
Thanks for clarifying, that was the part I missed, I think they should be handled equally. If this PR currently contains changes for both issues you mentioned, maybe we can focus on the issue quoted and make sure |
The latest version of the PR only contains just the first and the second (`select([])) can be done as a separate discussion as you mentioned. I've updated the original description to reflect this. The separate discussion is a low priority IMO... |
When focusing on the first problem:
The test cases are in the PR, excluding what I stated in the description:
To my point above, I also state in the description:
|
Supports changes made in pending [PR](parse-community/parse-server#7242). Can see [here](parse-community/parse-server#7245) for further discussion.
I see many places in the JS SDK and Parse Server where this is converted back and forth between JSON and comma delimited string. I am not sure why but surely inconvenient. Even the MongoDB client takes the project keys as JSON:
This conversion is done with many other parameters as well, looking at toJSON in the JS SDK. I agree that there could be some clean-up, maybe in steps:
|
My guess is that when the Parse Server, iOS, Android, and JS SDKs were originally created there "may" have not been native JSON encoders out at the time. I believe this was the case for iOS, so they resorted to manually parsing and creating dictionaries with data. In the Parse-Swift SDK, a JSON Encoder is used for everything that goes to/from the parse server (we don't parse anything manually in the SDK), so it looks like much of the manual parsing on the server-side is correct when comparing to something based on JSON encode/decode standard, at least in regards to what has been tested in Parse-Swift anyways (I have a couple apps with the SDK, but not running at a large scale yet). The Flutter SDK was probably just following exactly what the other SDKs were doing at the time. |
I think that makes sense, let's see which noble contributor takes on this clean-up. For this PR, I think you have nailed it down. Is this good for review yet? Is there a related PR necessary in the JS SDK? |
In the the future, in the other SDKs may want to even take this a step further and be modified to use native encoding/decoding instead of populating dictionaries. This can also be a case of, "if it isn't broken, don't fix it", but I personally don't trust myself to manually parse something.
Yup, it's ready |
Absolutely! |
🎉 This change has been released in version 5.0.0-beta.1 |
The label |
🎉 This change has been released in version 5.0.0 |
New Issue Checklist
Issue Description
The
keys
andexcludeKeys
on the server are not digesting actual JSON arrays, ["yolo",...], but instead digesting"yolo,..."
JS treats both of these the same (I discuss why below), but the server doesn't like it the way the Swift JSON encoder sends an encoded array for these properties,["yolo",...]
. Note that this is the JSON encoder straight from Apples Swift source code and not the custom one used here for ParseObjects, so if it was encoding arrays incorrectly I'm sure it would have been caught awhile ago as the Apple JSON encoder is used by a ton of people.At first glance this may appear to be a client side bug as there are currently server-side tests and the JS SDK(select and exclude), Flutter SDK (keysToReturn and excludeKeysToReturn), and the Android SDK (selectedKeys) uses it. The iOS SDK uses
selectedKeys
, but never sends them to the server, instead it strips the keys not selected after the server returns theParseObject
, so I'll ignore this SDK for the rest of the discussion. Below is why I believe the above SDKs work, but also why their current design (which can remain the same) has led to the problem not being discovered until now:select
andexclude
. Instead, they all join array elements into astring
separated by commas before sending to the server, always sending something like,"yolo,..."
which isn't an JSON array. This is why their implementations work with the current Parse Server implementation. Conversely, the Parse-Swift SDK uses Apples native JSON encoder and sends["yolo",...]
. When I make the Parse-Swift use a join array like the aforementioned SDKs, it works fine with the current implementation on the server."$all":[2,3,4]
):keys
andexcludeKeys
by stating:IMO this deviates from purpose of REST and JSON as it suggests manually parsing/creating lists/strings instead of using underlying libraries that encode/decode JSON based on standards. I’ll create a PR to fix this as well
The linked PR has the possibility of being breaking change for some users due to:I didn't attempt to make that old test case work anymore,because I don't think the feature should have been there in the first place, but I'm open to discussion on this.Approach
Make
keys
andexcludeKeys
use the same strategy as a similar property likeinclude
which actually digests a JSON string array,parse-server/src/Routers/ClassesRouter.js
Lines 60 to 68 in b4920a6
Steps to reproduce
string
forkeys
orexcludeKeys
. You can use the links for each SDK above. You can see an example when the issue was first discovered on Parse-Swift, .select() in finds and firsts does not seem to exclude any fields Parse-Swift#86select
orexcludeKey
queryActual Outcome
All keys will be returned as the server ignores the selected or excludedKeys
Expected Outcome
The server should honor what ever keys you select/exclude in an JSON array
Failing Test Case / Pull Request
Not possible on the server side because the test cases use the JS SDK and I mentioned above JS doesn’t actually send JSON arrays forkeys
andexcludeKeys
, instead it joins the array into a comma delineated string on the client side, essentially removing the fact that it’s an array. To write this test, you would have to make the JS SDK send a real array, have that PR approved, bump JS on the server, etc.Environment
Server
master
,4.5.0
Docker linux
,macOS
local
Database
mongo
,postgres
4.4
,13.2
local
Client
Parse-Swift
1.1.0
Logs
The text was updated successfully, but these errors were encountered: