Possible data retrieval issue

We are facing an issue with while running a query on the User table. We running a simple query to return a match on a users phoneNumber Column, on the rest API everything works as expected. However when using Swift API things get a bit interesting. When the find method is called results return as expected, however findFirst always return a result even if the query dosent match.

i suspect the issue has to do with the PersistenceServiceUtils class in the findFirstOrLast method, or could just be me :slight_smile:

Backendless Version (6.x )

Client SDK (Swift )

Application ID 2E6E6142-3600-6FA9-FF2E-462B0F504F00

Expected Behavior

Please describe the expected behavior of the issue, starting from the first action.

1.Create a DataQueryBuilder
2. set the where clause "phoneNumber = (userPhoneNumber)
3.findFirst method to return first matched object

Actual Behavior

  1. findFirst method ( and yes we triple checked that we are calling the one with queryBuilder as an argumentment)
  2. always return an object regardless of the query result

Reproducible Test Case

   let queryBuilder = DataQueryBuilder()
    queryBuilder.whereClause = "phoneNumber = \(phoneNumber)"

This Works as expecetd:

        Backendless.shared.data.ofTable("Users").find(queryBuilder: queryBuilder, responseHandler: { (response) in
            print(response)
        }) { (error) in
            print(error)
        }

This always return a result with the same query

Backendless.shared.data.ofTable("Users").findFirst(queryBuilder: queryBuilder, responseHandler: { (response) in
            print(response)
        }) { (error) in
            print(error)
        }

Hello @Omar_Darwish,

As far as your phoneNumber field is String, your query misses quotes around the phone number variable:

queryBuilder.whereClause = "phoneNumber = '\(phoneNumber)'"

Please, notice that the findFirst/findLast/findById methods don’t use whereClause in their queries, it will be ignored.
The findFirst/findLast methods always return the first/last data object saved in the data store.
The findById method return only the object with corresponding objectId.

You can specify the relationsPageSize, related and relationsDepth for these methods query.

Regards,
Olha

Olha,

Thank you for the reply.

I am pretty sure that the where clause is not the issue because we have tried your suggestion before posting this issue however when we encapsulate the phoneNumber in ’ ’ both methods return data which don’t match.

for example if i we encapsulate the phoneNumber in ‘1’ the both methods return all the phone numbers in the user table.

however if we don’t encapsulate it in ’ ’ the find method always returns the correct user instance.

regarding the find first/find last methods when never called them directly and we have noticed that they don’t accept a where clause directly however the method can be invoked with a dataQueryBuilder as an argument and this is the where clause is set.

as for find with ID it dosent fit our use case as we don’t have the object id, the entire purpose of the query is to return the first EXACT match and then run a separate command based on the returned objectId.

Thanks again for the prompt reply

I’ve tested your code snippet with your database and thats what I’ve got

let phoneNumber = "971501308152"
let queryBuilder = DataQueryBuilder()
queryBuilder.whereClause = "phoneNumber = '\(phoneNumber)'"
        
Backendless.shared.data.ofTable("Users").find(queryBuilder: queryBuilder, responseHandler: { (response) in
    print("(1) \(response)")
}) { (error) in
    print(error)
}
        
Backendless.shared.data.ofTable("Users").findFirst(queryBuilder: queryBuilder, responseHandler: { (response) in
    print("(2) \(response)")
}) { (error) in
    print(error)
}

Result:

It’s correct - we receive an array with 1 object with the phoneNumber = "971501308152" in the find response and the first object in the findFirst response.

Now I’ll change the phone number:

let phoneNumber = "11111"
// other code is the same

Result:

And it’s also correct - we don’t receive anything in the find response because there is no record with phoneNumber = 11111 but as far as the Users table is not empty we receive the first object in the findFirst response.

Regards,
Olha

Yes, these methods accept DataQueryBuilder as an argument but they ignore any parameters except the relationsPageSize, related and relationsDepth. The whereClause parameter is ignored in these methods.

Regards,
Olha

Thank you for the explanation

The results you got are the same exact results we got, however i think the confusion happened with the get first method, as the method accepts a dataQueryBuilder as a parameter but ignores it. To be honest i still cant wrap my head around it, why would you give me an option to pass in a dataQueryBuilder if its gone be completely ignored.

Thank you for shedding some light on the topic, i think this would be a valuable mention in the documentation.

method accepts a dataQueryBuilder as a parameter but ignores it.

It doesn’t ignore the the relationsPageSize, related and relationsDepth parameters of the DataQueryBuilder, e.g. for the case when you want to retrieve the first object with its relations.

Regards,
Olha