Class Name: QueryUtils¶
Last Updated: 2025-10-22 Source Code: QueryUtils.cls
API Name: QueryUtils Type: Utility (Query Builder) Test Coverage: Not specified
Business Purpose¶
This utility class provides a flexible framework for building SOQL queries dynamically at runtime, supporting field-level security checking and automatic translation for picklist values. It enables AANP to create reusable query logic that adapts to different security contexts and user permissions while maintaining clean separation between query construction and business logic.
Class Overview¶
Scope and Sharing¶
- Sharing Model: N/A (no sharing keyword - inherits from caller)
- Access Modifier: public
- Interfaces Implemented: None (defines internal Expression interface)
Key Responsibilities¶
- Dynamically builds SOQL queries using builder pattern
- Provides SELECT, FROM, and WHERE clause construction
- Enforces field-level security (FLS) validation for accessible fields
- Automatically translates picklist and multi-picklist fields using toLabel()
- Prevents duplicate field selection with case-insensitive tracking
- Supports relationship field traversal and nested expressions
- Handles sub-queries with proper parenthesis formatting
Public Methods¶
QueryUtils (Constructor)¶
Purpose: Creates a new query builder instance for the specified SObject type.
Parameters:
- table (Schema.SObjectType): The SObject type to query
Returns:
- QueryUtils: New instance configured for the specified object
Usage Example:
QueryUtils query = new QueryUtils(Account.SObjectType);
query.getSelectClause().addField(Account.Name);
query.getSelectClause().addField(Account.Industry);
String soql = query.buildSOQL();
// Result: "SELECT Name, Industry FROM Account"
Business Logic: - Initializes enforceFLS to false (not currently implemented) - Creates SelectClause with table and FLS flag - Creates FromClause with table name
getSelectClause¶
Purpose: Returns the SELECT clause builder for adding fields.
Returns:
- SelectClause: The SELECT clause builder instance
Usage Example:
QueryUtils query = new QueryUtils(Contact.SObjectType);
SelectClause select = query.getSelectClause();
select.addField(Contact.FirstName)
.addField(Contact.LastName)
.addField(Contact.Email);
buildSOQL¶
Purpose: Generates the complete SOQL query string from all configured clauses.
Returns:
- String: The complete SOQL query
Usage Example:
QueryUtils query = new QueryUtils(Account.SObjectType);
query.getSelectClause().addField(Account.Name);
query.setWhereClause('WHERE Industry = \'Technology\'');
String soql = query.buildSOQL();
// Result: "SELECT Name FROM Account WHERE Industry = 'Technology'"
Business Logic: - Builds SELECT clause first - Appends FROM clause - Appends WHERE clause if present - Trims final result
setWhereClause¶
Purpose: Sets the WHERE clause for the query.
Parameters:
- whereClause (String): Complete WHERE clause including "WHERE" keyword
Returns:
- void
Inner Classes¶
Expression Interface¶
Purpose: Contract for classes capable of generating SOQL expressions.
Method:
- String buildSOQL(): Generates SOQL fragment for the expression
SelectClause Class¶
Purpose: Expression implementation that builds SELECT clauses.
Key Methods:
addField(SObjectField field)¶
Purpose: Adds a field to the SELECT clause with automatic FLS checking.Business Logic: - Checks if field is accessible via isAccessible() - Adds field name to SELECT clause - Applies toLabel() for picklist/multi-picklist fields - Prevents duplicates using lowercase field name tracking
addFields(Schema.SObjectField[] fields)¶
Purpose: Convenience method to add multiple fields at once.addField(String field, Boolean translatable)¶
Purpose: Adds a field by name with optional translation.FieldExpression Class¶
Purpose: Simple expression that constructs field paths with optional relationship traversal and translation.
FromClause Class¶
Purpose: Expression implementation for FROM clauses.
ComplexExpression Abstract Class¶
Purpose: Base class for expressions that support nested expressions.
Private/Helper Methods¶
join¶
Purpose: Joins expression values using specified separator, handling sub-queries with parentheses.
Called By: SelectClause.buildSOQL()
Dependencies¶
Apex Classes¶
- None (standalone utility)
Salesforce Objects¶
- Uses Schema API for any SObject type
- Field-level security permissions for current user
Custom Settings/Metadata¶
- None
External Services¶
- None
Design Patterns¶
- Builder Pattern: Fluent interface for constructing queries
- Strategy Pattern: Different expression types for different query components
- Composite Pattern: ComplexExpression contains nested expressions
- Template Method Pattern: Expression interface with multiple implementations
- Factory Pattern: Creates appropriate expression types based on input
Governor Limits Considerations¶
SOQL Queries: None (builds query strings only) DML Operations: None CPU Time: Minimal - string concatenation and iteration Heap Size: Small - stores field names and expressions in memory
Bulkification: N/A (utility class for query building) Async Processing: N/A (synchronous utility)
Note: The queries built by this class are subject to normal SOQL governor limits when executed.
Error Handling¶
Strategy: No error handling implemented Logging: None User Notifications: None
Critical Gaps: - No validation of SObject type validity - No validation of field names - No SQL injection prevention for WHERE clauses - No exception handling for invalid field access - enforceFLS flag is set but never actually enforced beyond isAccessible() check
Security Considerations¶
Sharing Rules: Inherits from caller (no sharing keyword) Field-Level Security: Partially enforced via isAccessible() check CRUD Permissions: Not checked Input Validation: None for WHERE clause strings
Security Concerns: - enforceFLS flag exists but is not fully implemented - WHERE clause accepts raw strings without validation - No SQL injection protection - No validation that user has read permission on object
Security Notes: - isAccessible() check prevents querying inaccessible fields - toLabel() automatically applies for picklist translation - Runs in caller's context due to lack of sharing keyword
Test Class¶
Test Class: Not specified Coverage: Not specified Test Scenarios Needed: - Building simple SELECT statements - Adding fields with FLS restrictions - Picklist field translation - Relationship field traversal - WHERE clause construction - Sub-query handling - Duplicate field prevention - Invalid field/object handling
Changes & History¶
- 2018-06-11: Initial creation by Lopa
Pre-Go-Live Concerns¶
CRITICAL - Fix Before Go-Live¶
- FLS ENFORCEMENT NOT IMPLEMENTED: enforceFLS flag is set but never actually used beyond isAccessible() check
- NO SQL INJECTION PROTECTION: WHERE clause accepts raw strings without validation or sanitization
- NO ERROR HANDLING: No exception handling for invalid fields, objects, or permissions
- SECURITY BYPASS RISK: Inherits sharing from caller - could expose data in unsafe contexts
HIGH - Address Soon After Go-Live¶
- Add comprehensive error handling: Catch and handle invalid SObject types and fields
- Implement proper exception types: Create custom exceptions for query building failures
- Add WHERE clause validation: Prevent SQL injection and validate clause construction
- Complete FLS enforcement: Fully implement enforceFLS flag throughout all methods
- Add CRUD permission checks: Verify user has read permission on queried objects
MEDIUM - Future Enhancement¶
- Add ORDER BY, GROUP BY, HAVING clauses: Support additional SOQL clauses
- Implement query optimization: Suggest optimizations and add performance monitoring
- Add aggregate function support: Support SUM, COUNT, AVG, etc.
- Consider query caching: Cache frequently used query patterns
- Add LIMIT and OFFSET support: Enable pagination
LOW - Monitor¶
- Query performance and complexity: Monitor generated queries for optimization opportunities
- Usage patterns: Track which features are most used
- Field access patterns: Review for security compliance
- Duplicate prevention effectiveness: Ensure no unnecessary field duplication
Maintenance Notes¶
Complexity: Medium Recommended Review Schedule: Annually or when major SOQL features are added
Key Maintainer Notes: - This is a foundational utility class used across the application - changes require extensive testing - The enforceFLS flag exists but is not fully implemented - security gap that needs addressing - Class was created in 2018 and uses older coding patterns - consider modernization - WHERE clause handling is particularly risky - no SQL injection protection - The join() method handles sub-query parentheses automatically - Case-insensitive field tracking prevents duplicate SELECT fields - Picklist translation is automatic based on field type
Critical Dependencies: - Schema API must be available - Field-level security must be properly configured - Calling code must handle query execution and results
Usage Guidelines: - Always use for dynamic queries where fields are not known at compile time - Do not use if static SOQL is sufficient - Be cautious with WHERE clause construction to prevent SQL injection - Test thoroughly with different user permission sets - Consider using binding variables in consuming code for WHERE clause parameters
Common Pitfalls: - WHERE clause is just a string - no validation or safety checks - enforceFLS flag is misleading - doesn't fully enforce FLS - No support for ORDER BY, LIMIT, or other common SOQL features - Sub-queries must be manually constructed - Relationship fields require manual path construction