Intermediate 25 min read

Bulkify the Logic

By the end of this lesson, you'll be able to:

  • Combine both overlap checks into one complete, bulk-safe handler method
  • Confirm the entire method runs exactly one SOQL query regardless of batch size
  • Trace through a realistic 50-request batch scenario

Prerequisites: "Handle Overlapping Requests"

The complete, bulk-safe handler

public class LeaveRequestTriggerHandler {
    public void beforeInsert(List<Leave_Request__c> newRequests) {
        Set<String> employeeNames = new Set<String>();
        for (Leave_Request__c req : newRequests) {
            employeeNames.add(req.Employee_Name__c);
        }

        List<Leave_Request__c> existingRequests = [
            SELECT Id, Employee_Name__c, Start_Date__c, End_Date__c
            FROM Leave_Request__c
            WHERE Employee_Name__c IN :employeeNames AND Status__c != 'Rejected'
        ];

        for (Leave_Request__c newReq : newRequests) {
            for (Leave_Request__c existing : existingRequests) {
                if (newReq.Employee_Name__c == existing.Employee_Name__c
                    && datesOverlap(newReq.Start_Date__c, newReq.End_Date__c, existing.Start_Date__c, existing.End_Date__c)) {
                    newReq.Start_Date__c.addError('This leave request overlaps with an existing request.');
                }
            }
        }

        for (Integer i = 0; i < newRequests.size(); i++) {
            for (Integer j = i + 1; j < newRequests.size(); j++) {
                Leave_Request__c reqA = newRequests[i];
                Leave_Request__c reqB = newRequests[j];
                if (reqA.Employee_Name__c == reqB.Employee_Name__c
                    && datesOverlap(reqA.Start_Date__c, reqA.End_Date__c, reqB.Start_Date__c, reqB.End_Date__c)) {
                    reqB.Start_Date__c.addError('This request overlaps with another request in the same submission.');
                }
            }
        }
    }

    private Boolean datesOverlap(Date startA, Date endA, Date startB, Date endB) {
        return startA <= endB && startB <= endA;
    }
}

Every lesson from this module combined into one working class — one query, two purely in-memory comparison passes, one shared helper method.

Tracing a 50-request batch

Inserting 50 Leave_Request__c records across 10 different employees at once: one SOQL query fetches every existing request for those 10 employees; the new-vs-existing comparison loop runs at most 50 × (however many existing requests those 10 employees have) — pure in-memory work; the new-vs-new comparison runs at most 50 × 49 / 2 pair checks — also pure in-memory. Total SOQL queries: 1, regardless of whether the batch was 5 records or 200.

Exercise

As a comment, confirm this handler stays well under the 100-SOQL-query limit even for a 200-record insert, and explain why.

Show hint

Count how many queries actually run, independent of batch size.

APEX

Bulkify the Logic Quiz

1. How many total SOQL queries does the complete handler run for a batch of 200 new requests?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

This lesson assembles the complete handler method — both overlap checks together — and confirms the whole thing runs exactly one query no matter how large the batch is.