10

Our app uses a lot of dynamic SOQL, and in a client org I'm currently getting an error which I can't explain when we're performing a large query against account, including subqueries for all related lists on the page layout.

I've boiled it down to this (ignore line breaks in the string, just added them for readability):

String q = 'SELECT OwnerId,
    (SELECT Name FROM Conversations__pr LIMIT 5)
    FROM Account WHERE Id = \'abc123467890abc\'';

SObject queryResult = Database.query(q);
System.Debug(queryResult.getSObjects('Conversations__pr'));

Conversation__c is an object configured by the client that has a lookup to Contact, hence it should be available via a child relationship with the suffix __pr from Account:

Dev console query tool results

AND YET!

if I run the above code via Execute Anonymous in the dev console, I get this:

Line: 10, Column: 1 System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: Account.Conversations__r

My code definitely does not use 'Conversations__r', so I suspect there's a platform bug at play here.

Further Findings

If I change queryResult to be an instance of Account rather than SObject, then queryResult.Conversations__pr returns the data expected, but no, I can't change the code to that because this does need to be dynamic. I can't find any references to this kind of issue with getSObjects, so am I doing something dumb that I can't see or is this a bug?

2 Answers 2

9

Ok, I'm guessing Salesforce might hide their known issues from being crawled by search engines. Typed in getSObjects into the success community and the first thing that appeared was a known issue describing exactly this scenario:

https://success.salesforce.com/issues_view?id=a1p30000000SvzXAAS

Apparently this has been reported by zero users, but maybe because there's no "This issue affects me" box at the top of the screen as there should be because it's a "No Fix" bug. That's just great.

No Fix - Salesforce Engineering Management determined that a fix for the issue is not possible.

4
  • 3
    Interesting. I didn't even know Contact relationships could be traversed from Person Account SOQL this way. FWIW I tried the same thing out in a client sandbox I have that uses Person Accounts. I wanted to see if I could get clever and use getPopulatedFieldsAsMap or JSON.serialize. Neither one seems to work on Contact child relationships. So perhaps your best bet is just, any PersonSomethings or __pr child relationships should just be queried separately via the Contact object. At least that is something you can do dynamically enough.
    – Charles T
    Commented Feb 26, 2018 at 4:56
  • Yeah it's a bit of a pain, but I'll have to separate out those relationships, run the other query and then put it all back together into a cohesive whole again.
    – Matt Lacey
    Commented Feb 26, 2018 at 5:16
  • I wonder what their special hack is. Maybe at compile time, references to person child relationships are transformed into something else.
    – Charles T
    Commented Feb 26, 2018 at 5:24
  • Having hit this again (I'd forgotten about it in the mean time until I tried to fix the same problem as before) I just took the dumb route and if automatically try and query the contact direct for each relationship that fails on the account.
    – Matt Lacey
    Commented Aug 23, 2018 at 2:07
1

It would seem that the base problem is still at issue (getSObjects doesn't work for person child relationships).

BUT something changed in SObject.getPopulatedFieldsAsMap()!

Id i = '0016g000002q1OWAAY';
String s = 'SELECT Id, (SELECT Id, Name FROM CustomSamples__pr) FROM Account WHERE Id = :i';
Account[] accts = Database.query(s);    
Account a = accts[0];
Map<String, Object> smap = a.getPopulatedFieldsAsMap();
Object ochildren = smap.get('CustomSamples__pr');
List<CustomSample__c> samples = (List<CustomSample__c>)ochildren;
System.debug(samples);

This works now for me in a fresh trial org with Person Accounts just enabled. I get my child list safe and sound. So there is now a workaround: Instead of getSObjects, use getPopulatedFieldsAsMap, get from the correct child relationship key, and cast to a list of SObjects.

4
  • Will try and check that this works before I change the accepted answer, but you definitely get my upvote, and hopefully I'll find sometime in the next week to verify it!
    – Matt Lacey
    Commented Nov 26, 2019 at 1:20
  • TBH I have no idea how reproducible it is across orgs. But basically I just finished writing a managed package that, in part, parses out all the data it can find in a dynamic SOQL query through recursive use of getPopulatedFieldsAsMap. At design time, over a year ago, I tested code like the above and it did NOT work. Today, for a lark, I tested our UAT version of the package in a Person Accounts org and was baffled that it actually found on the Person child data. Tested this code again and it works now. So strange.
    – Charles T
    Commented Nov 26, 2019 at 5:00
  • I'm intruiged to try it. Could deifnitely be the author of getPopulatedFieldsAsMap was just a little more thorough than the dev original dev of getSObjects :)
    – Matt Lacey
    Commented Nov 26, 2019 at 5:28
  • Perhaps the SOQL to Apex engine got a bump in recent versions because polymorphic SOQL went GA?
    – Charles T
    Commented Nov 26, 2019 at 12:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .