Skip to content

Using Query.select() will break ParseObject.has() on undefined field from 2.5.1 #3999

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

Closed
promisenxu opened this issue Jul 5, 2017 · 21 comments
Labels
type:question Support or code-level question

Comments

@promisenxu
Copy link
Contributor

Issue Description

Starting from Parse Server 2.5.1, if a query has Query.select() , calling .has() on the returned object with a selected field that's undefined will return true.

Steps to reproduce

var query = new Parse.Query('ClassName');
query.include('FieldName');
query.select('FieldName');
query.get('objectId', {useMasterKey: true}).then(result => {
// Assume FieldName is undefined for the returned object
result.has('FiledName'); // This will return true.
});

Expected Results

.has() on a field with undefined value should return false, which is the behaviour up to 2.5.0.

Actual Outcome

Return true.

Environment Setup

  • Server

    • parse-server version (Be specific! Don't say 'latest'.) : 2.5.1, 2.5.2, 2.5.3
    • Localhost or remote server? (AWS, Heroku, Azure, Digital Ocean, etc): Heroku
  • Database

    • MongoDB version: 3.0.11 (MMAPv1)
    • Localhost or remote server? (AWS, mLab, ObjectRocket, Digital Ocean, etc): mLab
@flovilmart
Copy link
Contributor

Thanks for reporting the issue! We’ll have a look shortly!

@adirgan
Copy link

adirgan commented Jul 8, 2017

This affected my application also I had to return from version to 2.5.0 because I can not get certain data

flovilmart added a commit that referenced this issue Jul 8, 2017
flovilmart added a commit that referenced this issue Jul 8, 2017
@flovilmart
Copy link
Contributor

@adirgan, @promisenxu I just added a test, and waiting for CI to complete, but so far, this test works as expected. #4004. Can you please tell me where this test doesn't match your issue? Also, can you post the logs when running with VERBOSE=1?

@logicsb
Copy link

logicsb commented Jul 11, 2017

i had same problem, when i use select and the field is pointer type and the value is undefined. the new parse version returns an JSON with all fields of this pointer with undefined value. Expected are the selected field return an undefined value not an JSON object with undefined values on the fields.

@flovilmart
Copy link
Contributor

So is it possible to tell me where my test is wrong??

@logicsb
Copy link

logicsb commented Jul 11, 2017

On your test @flovilmart you have set an empty object on the field named 'field'. In my case, the value of the 'field' should be undefined to replicate the issue

@flovilmart
Copy link
Contributor

In my test, the obj has no value for the field key, and obj1 has an object. And it works as expected. Can you post and example test that fails at CI because I don’t get it

@logicsb
Copy link

logicsb commented Jul 11, 2017

I think its simple. You can add console.log(result.get('field')) on your test. In this case are expected undefined. In my case returns an json like {"__type":"Pointer","className":"OtherObject","objectId":undefined} and all of others fields have undefined value. If you need i can provide an screen with log with VERBOSE=1

@flovilmart
Copy link
Contributor

But you realize that the obj.has(‘field’) works as expected right?

@flovilmart
Copy link
Contributor

@logicsb verbose logs of the query response:

verbose: REQUEST for [GET] /1/classes/TestObject: {
  "where": {},
  "include": "field",
  "keys": "field"
} method=GET, url=/1/classes/TestObject, user-agent=node-XMLHttpRequest, Parse/js1.10.0 (NodeJS 7.4.0), accept=*/*, content-type=text/plain, host=localhost:8378, content-length=194, connection=close, , include=field, keys=field
verbose: RESPONSE from [GET] /1/classes/TestObject: {
  "response": {
    "results": [
      {
        "objectId": "7IsbXHTdSW",
        "createdAt": "2017-07-11T23:16:38.388Z",
        "updatedAt": "2017-07-11T23:16:38.388Z"
      },
      {
        "objectId": "puId6aR3zn",
        "field": {
          "objectId": "JMchm2AACl",
          "createdAt": "2017-07-11T23:16:38.388Z",
          "updatedAt": "2017-07-11T23:16:38.388Z",
          "__type": "Object",
          "className": "OtherObject"
        },
        "createdAt": "2017-07-11T23:16:38.610Z",
        "updatedAt": "2017-07-11T23:16:38.610Z"
      }
    ]
  }
} results=[objectId=7IsbXHTdSW, createdAt=2017-07-11T23:16:38.388Z, updatedAt=2017-07-11T23:16:38.388Z, objectId=puId6aR3zn, objectId=JMchm2AACl, createdAt=2017-07-11T23:16:38.388Z, updatedAt=2017-07-11T23:16:38.388Z, __type=Object, className=OtherObject, createdAt=2017-07-11T23:16:38.610Z, updatedAt=2017-07-11T23:16:38.610Z]
verbose: REQUEST for [GET] /1/classes/TestObject: {
  "where": {},
  "include": "field",
  "keys": "field"
} method=GET, url=/1/classes/TestObject, user-agent=node-XMLHttpRequest, Parse/js1.10.0 (NodeJS 7.4.0), accept=*/*, content-type=text/plain, host=localhost:8378, content-length=194, connection=close, , include=field, keys=field
verbose: RESPONSE from [GET] /1/classes/TestObject: {
  "response": {
    "results": [
      {
        "objectId": "7IsbXHTdSW",
        "createdAt": "2017-07-11T23:16:38.388Z",
        "updatedAt": "2017-07-11T23:16:38.388Z"
      },
      {
        "objectId": "puId6aR3zn",
        "field": {
          "objectId": "JMchm2AACl",
          "createdAt": "2017-07-11T23:16:38.388Z",
          "updatedAt": "2017-07-11T23:16:38.388Z",
          "__type": "Object",
          "className": "OtherObject"
        },
        "createdAt": "2017-07-11T23:16:38.610Z",
        "updatedAt": "2017-07-11T23:16:38.610Z"
      }
    ]
  }
} results=[objectId=7IsbXHTdSW, createdAt=2017-07-11T23:16:38.388Z, updatedAt=2017-07-11T23:16:38.388Z, objectId=puId6aR3zn, objectId=JMchm2AACl, createdAt=2017-07-11T23:16:38.388Z, updatedAt=2017-07-11T23:16:38.388Z, __type=Object, className=OtherObject, createdAt=2017-07-11T23:16:38.610Z, updatedAt=2017-07-11T23:16:38.610Z]

@flovilmart
Copy link
Contributor

I'd gladly resolve the issue if only I could reproduce it

@logicsb
Copy link

logicsb commented Jul 12, 2017

In my case the issue is:

{  
      "createdAt":"2017-07-11T22:45:41.835Z",
      "updatedAt":"2017-07-12T01:00:45.819Z",
      "hive":{  },
      "object":{  
         "actor":{ },
         "group":{  
            "hive":{ }
         },
         "hive":{}
      },
      "objectId":"EscZ2woUYv"
}

hive: is a pointer to Hive and value is undefined on the parse-dashboard
object: is a pointer to Activity and value is undefined on the parse-dashboard
actor: is a pointer to _User and value is undefined on the parse-dashboard
...

I don't know, but before update the parse version, "object" field does not apear on the response JSON because your value is undefined.

i'm using select like

query.select("object")
query.select("object.actor")
query.select("object.group")
query.select("object.group.hive")
....

I think before version of parse are correct, if "object" is undefined don't need send an empty object on the response.

@flovilmart
Copy link
Contributor

Can you provide some code/open a PR with a failing test please?

@logicsb
Copy link

logicsb commented Jul 20, 2017

I think i have found the situation to cause this issue:

class Foo (name:String, status:String, content:String, object:Pointer< Foo>, user:Pointer<_User>)

var query = new Parse.Query("Foo");
query.include("object")
query.include("user")
query.select([
    'user',
    'user.name',
    'name',
    'content',
    'object',
    'object.name',
    'object.content'
])

if the object field is undefined this will return a JSON like:

{
    "user" : {"name" : "Smith"},
    "name" : "bla",
    "content" : "bla bla",
     "object" : {
         "user" : {}
     }
}

@dplewis
Copy link
Member

dplewis commented Aug 23, 2017

@flovilmart @montymxb This is how I reproduced the issue. This is a JS-SDK issue

  const obj = new Parse.Object('TestObject'); // Yay no foo
    obj.save().then(() => {
      const query = new Parse.Query('TestObject');
      query.select('foo');
      return query.get(obj.id);
    }).then((result) => {
      expect(result.has('foo')).toBe(false); // result.has('foo') returns true ?!?? :(
      done();
    }).catch(done.fail);

@dstarke
Copy link
Contributor

dstarke commented Sep 11, 2017

There was an issue in the JS-SDK where a query that selected sub-objects would cause the client to inject empty sub-objects at the parent levels in the selection path if an element in that path was not returned by the query. I believe that is the cause of the issues described here.

I have submitted a pull request to the JS-SDK with a fix along with some test cases for the root cause of this: parse-community/Parse-SDK-JS#477

@flovilmart
Copy link
Contributor

@dstarke, before we merge the JS fixes, I’ll add a test here to make sure he fix is efficient and we have no other regressions in here.

@flovilmart
Copy link
Contributor

@dplewis I ran your repro in the test suite, and it still didn't fail :/ Not sure how to go from there.

@promisenxu
Copy link
Contributor Author

Sorry for abandoning this thread - was dealing with some personal issues.

I'm not sure what is the current status of this. It seems that parse-community/Parse-SDK-JS#477 should fix this?

Let me try to create a test for this repo for this issue.

@promisenxu promisenxu mentioned this issue Oct 10, 2017
@promisenxu
Copy link
Contributor Author

promisenxu commented Oct 10, 2017

@flovilmart Figure out how to write a failed test case for this issue - the caveat is to also select a field of the pointer field. Pull Request #4245

@flovilmart
Copy link
Contributor

thanks for jumping back on it! We’ll review shortly and test against The fixed JS SDK :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:question Support or code-level question
Projects
None yet
Development

No branches or pull requests

7 participants