RC-287 - Restrict S9142 to prepared statements - #6067
Conversation
|
| void forInitializer(Connection conn) throws SQLException { | ||
| for (PreparedStatement ps = conn.prepareStatement("SELECT 1"); ps != null; ) { // Compliant: initializer runs once | ||
| break; | ||
| } | ||
| for (; conn.prepareStatement("SELECT 1") != null; ) { // Noncompliant | ||
| break; | ||
| } | ||
| } |
There was a problem hiding this comment.
⚠️ Quality: Deleted samples leave retained loop-detection paths untested
The old sample exercised two scenarios of isExecutedOncePerLoop that the new sample no longer covers: a call in a for-each expression (for (String s : Pattern.compile(";").split(text)) → compliant, hitting the current == anchor true branch for ForEachStatement) and the same construct nested inside an outer loop (forEachIterableInsideOuterLoop → the path at lines 70-78 where the outer-loop lookup succeeds and an issue is reported). Both branches are still reachable with prepareStatement and are now completely untested, so a regression in the once-per-iteration/nested-loop handling would pass CI, and the renamed file will show uncovered branches on new code.
Re-add the two dropped scenarios to PreparedStatementInsideLoopCheckSample, expressed with prepareStatement instead of Pattern.compile.:
void forEachExpression(Connection conn) throws SQLException {
for (PreparedStatement p : List.of(conn.prepareStatement("SELECT 1"))) { // Compliant: expression evaluated once
p.close();
}
}
void forEachExpressionInsideOuterLoop(Connection conn, List<Integer> ids) throws SQLException {
for (int id : ids) {
for (PreparedStatement p : List.of(conn.prepareStatement("SELECT 1"))) { // Noncompliant
p.close();
}
}
}
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
| <p>This is an issue when a database <code>PreparedStatement</code> object is created inside a loop body with a constant or loop-invariant SQL string | ||
| argument.</p> |
There was a problem hiding this comment.
💡 Quality: S9142 description scope and leftover generic wording are inaccurate
The new intro says the issue occurs when the statement is created "inside a loop body", but the check reports any prepareStatement call under a loop except the for initializer / for-each expression — the sample itself marks a call in a for condition as Noncompliant (for (; conn.prepareStatement("SELECT 1") != null; )). The impact bullets also still carry the pre-narrowing generic phrasing ("For database operations, ...", "especially when processing large collections or datasets") which implies non-database operations are in scope. Reword the intro to "inside a loop" and drop the "For database operations" qualifier now that the rule only covers prepared statements.
Fix 1: Match the documented scope to the implemented one (any position inside the loop, not just the body).
<p>This is an issue when a database <code>PreparedStatement</code> object is created inside a loop with a constant or loop-invariant SQL string
argument.</p>
- Apply fix
Fix 2: Remove the leftover "For database operations" qualifier from the impact list.
<li><strong>Resource exhaustion</strong>: Repeatedly creating parameterized query objects can exhaust server-side cursor or
statement handle limits, causing connection failures</li>
- Apply fix
Check a box to apply a fix or reply for a change | Was this helpful? React with 👍 / 👎
Code Review
|
| Auto-apply | Compact | Unblock |
|
|
|
Was this helpful? React with 👍 / 👎 | Gitar




Summary by Gitar
CompilationOrPreparationInLoopChecktoPreparedStatementInsideLoopCheckfor ruleS9142PreparedStatementcreations onlyThis will update automatically on new commits.