v5.2.0
13-August-2025
Scope
- New Query Result Methods
- Enhanced Mocking System (
SOQL&SOQLCache) - Documentation Improvements
- Performance Optimizations
- Code Quality Improvements
SOQL
- Added new result extraction methods:
toIds(),toIdsOf(), andnullsOrder(). - Enhanced subquery support with relationship name tracking.
- Improved mocking system with sequential stack functionality.
- Performance optimizations in string building and field handling.
- Better mock field stripping for subqueries and plain fields.
SOQLCache
- Enhanced mocking system with stack functionality supporting sequential mocks.
- Improved performance with optimized object instantiation and field conversion.
- Added null safety improvements and better error handling.
- Updated to API version 64.0 across all components.
Documentation
- Added comprehensive "Minimalistic Selectors" section with design philosophy and examples.
- Enhanced "Minimal Fields" documentation with performance benefits and best practices.
- Improved mocking documentation with stack functionality explanation.
- Added practical before/after examples for new query result methods.
API Version Update
All Apex classes have been updated to API version 64.0, ensuring compatibility with the latest Salesforce features and improvements.
Enhanced Mocking System
Both SOQL and SOQLCache now feature improved mocking capabilities with better performance and cleaner code organization.
SOQL Library Improvements
The standard SOQL library has received several mocking and performance enhancements:
Legacy Mock Consolidation
// Before: Duplicate code in deprecated methods
private static void setMock(String mockId, SObject record) {
SOQL.queryIdToMock.put(mockId, new List<SoqlMock>{ new SoqlMock().useLegacyMockingBehavior() });
SOQL.queryIdToMock.get(mockId).get(SOQL.queryIdToMock.get(mockId).size() - 1).thenReturn(record);
}
// After: Clean helper method
private static void setMock(String mockId, SObject record) {
SOQL.createLegacyMock(mockId).thenReturn(record);
}
private static SoqlMock createLegacyMock(String mockId) {
SoqlMock mock = new SoqlMock().useLegacyMockingBehavior();
SOQL.queryIdToMock.put(mockId, new List<SoqlMock>{ mock });
return mock;
}Enhanced Binder with Reset Capability
public class Binder {
public void reset() {
this.bindIndex = 0;
this.binding.clear();
}
}
// Usage in toString():
public override String toString() {
binder.reset(); // Better memory management
return this.builder.toString();
}SOQLCache Enhancements
SOQLCache now supports the same sophisticated mocking capabilities as the standard SOQL library, including sequential mock execution.
Sequential Mock Stack
You can now set up multiple mocks for the same query identifier, which will be consumed in FIFO (First In, First Out) order:
Test Setup
@IsTest
static void mockStack() {
// Setup multiple sequential mocks
SOQL.mock('mockingQuery').thenReturn(new Profile(Name = 'Test 1'));
SOQL.mock('mockingQuery').thenReturn(new Profile(Name = 'Test 2'));
SOQL.mock('mockingQuery').thenReturn(new Profile(Name = 'Test 3'));
// Test
SOQLCache.Cacheable query = SOQLCache.of(Profile.SObjectType)
.mockId('mockingQuery')
.whereEqual(Profile.Name, 'System Administrator');
Profile profile1 = (Profile) query.toObject(); // Returns 'Test 1'
Profile profile2 = (Profile) query.toObject(); // Returns 'Test 2'
Profile profile3 = (Profile) query.toObject(); // Returns 'Test 3'
Profile profile4 = (Profile) query.toObject(); // Returns 'Test 3' (reuses last)
}Modernized Mock API
The mocking system has been updated to use the modern .mock().thenReturn() pattern instead of the deprecated .setMock() methods:
Before
SOQL.setMock('ProfileQuery', mockProfile);After
SOQL.mock('ProfileQuery').thenReturn(mockProfile);Performance Optimizations
SOQL Library Performance Improvements
Optimized String Building
The toString() method now uses efficient String.join() instead of string concatenation:
// Before: String concatenation in loop
public override String toString() {
String query = '';
for (QueryClause clause : this.clauses) {
if (clause != null) {
query += ' ' + clause.toString(); // Inefficient O(n²) complexity
}
}
return query.trim();
}
// After: Efficient list-based joining
public override String toString() {
List<String> queryParts = new List<String>();
for (QueryClause clause : this.clauses) {
if (clause != null) {
queryParts.add(clause.toString());
}
}
return String.join(queryParts, ' '); // O(n) complexity
}Enhanced Field Handling
- Removed unnecessary null coalescing operations in field processing
- Optimized
doExist()method withsetLimit(1)for better performance - Improved
isEmpty()checks instead ofsize() > 0comparisons
SOQLCache Performance Improvements
Reduced Object Instantiation
Optimized cache storage operations to reuse proxy objects instead of creating multiple instances:
Before
new CacheStorageProxy(ofObject).apexTransaction().removeRecordsFromCache(records);
new CacheStorageProxy(ofObject).orgCache().removeRecordsFromCache(records);
new CacheStorageProxy(ofObject).sessionCache().removeRecordsFromCache(records);After
CacheStorageProxy proxy = new CacheStorageProxy(ofObject);
proxy.apexTransaction().removeRecordsFromCache(records);
proxy.orgCache().removeRecordsFromCache(records);
proxy.sessionCache().removeRecordsFromCache(records);Improved Field Conversion
Standardized field-to-string conversion throughout the codebase using .toString() instead of string concatenation:
// Consistent field conversion
this.cachedFields.add(field.toString());
return this.whereEqual(field.toString(), value);Code Quality Improvements
Enhanced Null Safety
Added proper null safety checks to prevent NullPointerExceptions:
public Id toId() {
return this.toObject()?.Id; // Safe null handling
}Optimized Boolean Logic
Improved performance in field validation with early return patterns:
Before
public Boolean hasAllRequestedFields(SObject record) {
Boolean hasCachedFields = true;
for (String field : this.cachedFields) {
hasCachedFields &= record.isSet(field);
}
return hasCachedFields;
}After
public Boolean hasAllRequestedFields(SObject record) {
for (String field : this.cachedFields) {
if (!record.isSet(field)) {
return false; // Early exit for better performance
}
}
return true;
}Cleanup and Optimization
- Removed unused variables and redundant code
- Optimized time calculations with direct numeric constants
- Improved error handling consistency
- Enhanced executor logic for better mock management
Breaking Changes
There are no breaking changes in this release. All optimizations maintain backward compatibility while improving performance and reliability.
Contributors
Thank you to all contributors who helped make this release possible through code optimization, testing, and feedback.