I am running this script from developer console.
List<Account> lstAccount = [SELECT Id, Name, BillingStreet From Account LIMIT 1];
System.debug(lstAccount);
Debug Log:
23:47:04:012 USER_DEBUG [5]|DEBUG|(Account:{Id=0019000001nNLGEAA4, Name=Acct_nm001, BillingStreet=xyz Road, RecordTypeId=01290000000iaNiAAI})
I never queried for RecordtypeId
in SOQL, but it is included in the list.
Although, if I run the query from the query editor, it is not showing RecordtypeId
column.
Is this by design? Then why not Salesforce is not providing us audit fields in the first scenario.
Best Answer
In Apex Code, the SOQL engine automatically includes RecordTypeId and Id in any query result, even if you don't ask for it. There are a few other hidden parameters that appear in a query when presented to the SOQL engine.
For example, if you don't include a LIMIT statement, or set it to higher than
1+Limits.getLimitQueryRows()-Limits.getQueryRows()
, the system automatically adds or changes the limit toLIMIT :1+Limits.getLimitQueryRows()-Limits.getQueryRows()
. This is how the governor limits are enforced. The exception to this is for Batchable classes that use a Database.getQueryLocator statement, where the limit is set 50,000,001 rows. Also, when you don't specify ALL ROWS, Apex Code silently includes a filterIsDeleted = FALSE
. In other words, whatever you put into your code isn't necessarily what will be executed by the SOQL engine.Note that this means the following two queries are (approximately) the same in Apex Code:
I don't know if there's a documented reason why RecordTypeId was specifically included, while audit fields were not, but I seem to recall that this behavior did not always exist in Apex Code, which suggests to me that some new SObject method was added that required this field to be present to function correctly. My best guess is that this field was needed for the Visualforce runtime engine to correctly render dynamic picklists on records.