There is some strangeness in the some standard Childrelationships. Most Relationships are as expected, but let us take Account and Quote as an example:
On Quote we have a standard lookup field Quote.AccountId - which is nice. Only if I do this
Schema.getGlobalDescribe().get('Account').getDescribe().getChildRelationships()
I will only get as a result (reduced)
... , {
"cascadeDelete" : false,
"childSObject" : "Quote",
"deprecatedAndHidden" : false,
"field" : "AccountId",
"junctionIdListNames" : [ ],
"junctionReferenceTo" : [ ],
"relationshipName" : null,
"restrictedDelete" : false
}, ...
Now here is the strangeness: why the relationshipName = null?? This I would NEVER expect. Instead I would expect relationshipName = 'Accounts' (plural of 'Account')
When I create a custom lookup from Quote to Account called 'Account__c', I will have to provide such a ChildRelationshipName. Here I would provide 'Accounts' as RelationshipName. This will result as expected in
... , {
"cascadeDelete" : false,
"childSObject" : "Quote",
"deprecatedAndHidden" : false,
"field" : "Account__c",
"junctionIdListNames" : [ ],
"junctionReferenceTo" : [ ],
"relationshipName" : "Quotes__r",
"restrictedDelete" : false
},...
So relationshipName = "Quotes__r". Brilliant. Exactly as expected! But why Salesforce can omit that relationshipName sometimes?
Why the heck do I need this?
I need to get all childRelationships dynamically to build a dynamic SOQL to query child objects dynamically using subqueries. I need to query all the quotes on account, too. Of course with the very same dynamic code. Now without a relationshipName I can not create the subquery. And even if I would be able to guess the name, the subquery does not work:
database.query('select Name, (select Name from Quotes) from Account where Id = \'0011n00001yZsqCAAS\' ');
This will cause an exception: System.QueryException: Didn't understand relationship 'Quotes' in FROM part of query call...
Sure, because there is no such child relationship Quotes, because Salesforce has left that thing blank.
But WHY? Is this a bug or a feature? Is there a pattern why and how Salesforce has decided for standard lookup fields in most cases provided a relationshipName but sometimes in rare cases to leave it blank? This feels super inconsistent to me!
My custom lookup works perfectly database.query('select Name, (select Name from Quotes__r) from Account where Id = '0011n00001yZsqCAAS' ');
Why relationshipName is not a mandatory thing even for salesforce standard fields? Is it on purpose to break the ability to write such subqueries? Has it other reasons?
Order.BilltoContactId
lookup field toContact
.