apex.lang.performance.ncino.operationsinloops.avoidoperationswithlimitsinloops.avoid-operations-with-limits-in-loops

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Database class methods, DML operations, SOQL queries, SOSL queries, Approval class methods, Email sending, async scheduling or queueing within loops can cause governor limit exceptions. Instead, try to batch up the data into a list and invoke the operation once on that list of data outside the loop.

Run Locally

Run in CI

Defintion

rules:
  - id: avoid-operations-with-limits-in-loops
    min-version: 1.44.0
    severity: ERROR
    languages:
      - generic
    metadata:
      category: performance
      references:
        - https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm
      technology:
        - salesforce
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
    message: Database class methods, DML operations, SOQL queries, SOSL queries,
      Approval class methods, Email sending, async scheduling or queueing within
      loops can cause governor limit exceptions. Instead, try to batch up the
      data into a list and invoke the operation once on that list of data
      outside the loop.
    patterns:
      - pattern-either:
          - pattern-inside: |
              for (...) {
                ...
              }
          - pattern-inside: |
              while (...) {
                ...
              }
          - pattern-inside: |
              do {
                ...
              } while (...);
      - pattern-either:
          - pattern: |
              Messaging.sendEmail(...);
          - pattern: >
              Approval.ProcessSubmitRequest $REQUEST = new
              Approval.ProcessSubmitRequest();
          - pattern: |
              System.enqueueJob(...);
          - pattern: |
              System.schedule(...);
          - pattern: |
              System.scheduleBatch(...);

Examples

AvoidOperationsWithLimitsInLoops.cls

public class AvoidOperationsWithLimitsInLoops {
	public void messageInsideOfLoop() {
		for (Integer i = 0; i < 151; i++) {
			Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
			// ruleid: avoid-operations-with-limits-in-loops
			Messaging.sendEmail(new Messaging.SingleEmailMessage[]{email});
		}
	}

	public void messageInsideOfLoop2() {
		for (Account a : accounts) {
			Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
			// ruleid: avoid-operations-with-limits-in-loops
			Messaging.sendEmail(new Messaging.SingleEmailMessage[]{email});
		}
	}

	public void messageInsideOfLoop3() {
		while (someCondition) {
			Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
			// ruleid: avoid-operations-with-limits-in-loops
			Messaging.sendEmail(new Messaging.SingleEmailMessage[]{email});
		}
	}

	public void messageInsideOfLoop4() {
		do {
			Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
			// ruleid: avoid-operations-with-limits-in-loops
			Messaging.sendEmail(new Messaging.SingleEmailMessage[]{email});
		} while (someCondition);
	}

	public void approvalInsideOfLoop() {
		for (Integer i = 0; i < 151; i++) {
			// ruleid: avoid-operations-with-limits-in-loops
			Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
			req.setObjectId(acc.Id);
			Approval.process(req);
			Approval.lock(acc);
			Approval.unlock(acc);
		}
	}

	public void approvalInsideOfLoop2() {
		for (Account a : accounts) {
			// ruleid: avoid-operations-with-limits-in-loops
			Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
			req.setObjectId(acc.Id);
			Approval.process(req);
			Approval.lock(acc);
			Approval.unlock(acc);
		}
	}

		public void approvalInsideOfLoop3() {
		while (someCondition) {
			// ruleid: avoid-operations-with-limits-in-loops
			Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
			req.setObjectId(acc.Id);
			Approval.process(req);
			Approval.lock(acc);
			Approval.unlock(acc);
		}
	}

	public void approvalInsideOfLoop4() {
		do {
			// ruleid: avoid-operations-with-limits-in-loops
			Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
			req.setObjectId(acc.Id);
			Approval.process(req);
			Approval.lock(acc);
			Approval.unlock(acc);
		} while (someCondition);
	}

	public void asyncInsideOfLoop() {
		for (Integer i = 0; i < 151; i++) {
			// ruleid: avoid-operations-with-limits-in-loops
			System.enqueueJob(new MyQueueable());
			// ruleid: avoid-operations-with-limits-in-loops
			System.schedule('x', '0 0 0 1 1 ?', new MySchedule());
			// ruleid: avoid-operations-with-limits-in-loops
			System.scheduleBatch(new MyBatch(), 'x', 1);
		}
	}

	public void asyncInsideOfLoop2() {
		for (Account a : accounts) {
			// ruleid: avoid-operations-with-limits-in-loops
			System.enqueueJob(new MyQueueable());
			// ruleid: avoid-operations-with-limits-in-loops
			System.schedule('x', '0 0 0 1 1 ?', new MySchedule());
			// ruleid: avoid-operations-with-limits-in-loops
			System.scheduleBatch(new MyBatch(), 'x', 1);
		}
	}

	public void asyncInsideOfLoop3() {
		while (someCondition) {
			// ruleid: avoid-operations-with-limits-in-loops
			System.enqueueJob(new MyQueueable());
			// ruleid: avoid-operations-with-limits-in-loops
			System.schedule('x', '0 0 0 1 1 ?', new MySchedule());
			// ruleid: avoid-operations-with-limits-in-loops
			System.scheduleBatch(new MyBatch(), 'x', 1);
		}
	}

	public void asyncInsideOfLoop4() {
		do {
			// ruleid: avoid-operations-with-limits-in-loops
			System.enqueueJob(new MyQueueable());
			// ruleid: avoid-operations-with-limits-in-loops
			System.schedule('x', '0 0 0 1 1 ?', new MySchedule());
			// ruleid: avoid-operations-with-limits-in-loops
			System.scheduleBatch(new MyBatch(), 'x', 1);
		} while (someCondition);
	}
}