Avoid Linear READ TABLE Scans Inside Loops
Overview
Avoid linear READ TABLE scans inside loop iterations.
ATC Finding Messages:
READ TABLE ... WITH KEY inside a loop scans the table on every passREAD TABLE ... WHERE inside a loop scans the table on every pass
Rationale
A READ TABLE that addresses rows through WITH KEY or WHERE walks the internal table entry by entry, so placing it inside a LOOP turns the routine into an O(N*M) scan: doubling both tables quadruples the work, and code that passes a smoke test with fifty rows stalls once production feeds it fifty thousand. Declaring the looked-up table as HASHED or SORTED with the searched component as key, or resolving the values in one pass before the loop, keeps each lookup at constant or logarithmic cost. The rule reports only the linear access forms; reads through WITH TABLE KEY, BINARY SEARCH or INDEX address a declared key and stay unreported.
Non-Compliant
LOOP AT lt_orders INTO DATA(ls_order).
READ TABLE lt_items INTO DATA(ls_item) WITH KEY order_id = ls_order-id.
APPEND ls_item TO lt_selected.
ENDLOOP.Compliant
DATA lt_items_by_id TYPE HASHED TABLE OF ty_item WITH UNIQUE KEY order_id.
lt_items_by_id = VALUE #( FOR ls_item IN lt_items ( ( ls_item ) ) ).
LOOP AT lt_orders INTO DATA(ls_order).
READ TABLE lt_items_by_id INTO DATA(ls_item) WITH TABLE KEY order_id = ls_order-id.
APPEND ls_item TO lt_selected.
ENDLOOP.Configuration & Thresholds
This check can be fine-tuned directly in the ATC Check Variant Editor (CHKV) in Eclipse ADT:
| Parameter Name | Data Type | Default Value | Description & Guidance |
|---|---|---|---|
CHECK_WITH_KEY | Boolean | true | Report READ TABLE ... WITH KEY inside a loop, because the key is compared against every row. Disable when a codebase only treats the WHERE form as a defect while table types are still being converted. |
CHECK_WHERE | Boolean | true | Report READ TABLE ... WHERE inside a loop, because a WHERE condition never engages a table key and always visits all rows. Disable to allow condition based reads during a migration. |
Suppression
To suppress findings for this rule, append the pseudo-comment to the statement:
" Standard pseudo-comment:
... "#EC NO_READ_LOOP
" SAP CI_ prefix format:
... "#EC CI_NO_READ_LOOPAccess forms
Only READ TABLE statements inside a LOOP, DO or WHILE body are evaluated, and key access is separated from linear access:
| Access form | Inside a loop |
|---|---|
READ TABLE lt INTO ls WITH KEY f = v. | reported (NO_RD_WKEY) |
READ TABLE lt TRANSPORTING NO FIELDS WITH KEY f = v. | reported (NO_RD_WKEY) |
READ TABLE lt INTO ls WHERE f = v. | reported (NO_RD_WHRE) |
READ TABLE lt INTO ls WITH TABLE KEY f = v. | allowed, addresses a declared key |
READ TABLE lt INTO ls WITH KEY f = v BINARY SEARCH. | allowed, logarithmic search |
READ TABLE lt INTO ls INDEX lv_index. | allowed, constant time |
Notes
READ LINE,READ REPORT,READ DATASETand the EMLREAD ENTITIESform are not internal table reads and are never reported.- Keyword tokens are only recognised when they carry no compiler reference, so a variable or component named
whereorkeycannot raise a finding. - The loop does not have to iterate over the table being read; a linear read of any table while a loop is open repeats the scan on every pass.
- Fix a finding by declaring the read table
HASHEDorSORTEDwith the searched component as key and reading it withWITH TABLE KEY, or by resolving all lookups in a single pass before the loop. - Suppress an intentional read with
"#EC NO_READ_LOOPon the statement.
Related Rules
- Avoid Unindexed Nested LOOP AT Statements —
#EC NO_NESTED_LOOP - Use WITH KEY Instead of WHERE in READ TABLE Statements —
#EC PREF_READ_KEY - Avoid Database Queries Inside Loops (N+1 Query Antipattern) —
#EC NO_DB_IN_LOOP - Do Not Mutate or Sort Tables Currently Being Looped —
#EC NO_MOD_LOOP_TAB
Technical Details
- Native ATC Class:
/SKYL/CL_NO_READ_IN_LOOP - ABAP Implementation: /skyl/cl_no_read_in_loop.clas.abap
- Rule Metadata: rules-data.mjs (Line 5955)