Skip to content

v5.2.0

Choose a tag to compare

@pgajek2 pgajek2 released this 13 Aug 19:59

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(), and nullsOrder().
  • 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 with setLimit(1) for better performance
  • Improved isEmpty() checks instead of size() > 0 comparisons

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.