SOQL results returning RecordTypeId which is not included in query

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 to LIMIT :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 filter IsDeleted = 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:

Account[] accounts1 = [SELECT Id, RecordTypeId, Name, (SELECT Id, RecordType, Name FROM Contacts WHERE IsDeleted = FALSE) FROM Account WHERE IsDeleted = FALSE LIMIT :1+Limits.getLimitQueryRows()-Limits.getQueryRows()];
Account[] accounts2 = [SELECT Name, (SELECT Name FROM Contacts) FROM Account];

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.


I would like to point CurrencyISOCode which would also included by default, if your Org is Multicurrency enabled one.

Tags:

Soql