PdoSelectRowCountAssumption
warning native off by defaultGroup: Probable bugs
Detect rowCount on a PDOStatement prepared from a SELECT and used as a total result count under an explicitly enabled portable-count contract.
Example
<?php
function bad(PDO $pdo) { $s = $pdo->query('SELECT * FROM items'); $count = $s->rowCount(); }Reported:
- line 2: Use an explicit count query for portable row counts.
Detection
- Report rowCount on a PDOStatement prepared from a SELECT and used as a total result count under an explicitly enabled portable-count contract.
- Resolve builtin calls and named arguments before checking the contract. Project-local callees are considered only when their bodies or immutable summaries establish the required facts. The default is disabled; enable only when the stated intent matches the application.
- The receiver is a statement either when its resolved type is PDOStatement or when its value is proven to be the result of a builtin
PDO::query()call. The second proof looks the method up independently of the target version and does not depend on a declared return type; a subclass that overridesquery()is not a builtin call. Consequentlyquery()andprepare()statements are reported alike for every supported target version. - For flow-dependent conditions, require a reachable source-to-use path with no intervening invalidation. Unknown calls, ambiguous aliases, recursion or analysis-budget exhaustion cannot establish definite facts.
Exceptions (no report)
- Non-SELECT statements, COUNT queries fetched as a value, known driver-specific intentional behavior and unknown query origin are excluded.
- Unresolved targets, incomplete required facts, suppressed findings and PHP versions lacking the referenced API or language feature produce no report. User declarations shadowing builtin names are not builtin contracts.
Fix
No automatic fix: replacing the query changes result shape, cost and transaction consistency.
PHP versions
Apply only on PHP versions supporting the referenced APIs and syntax (within PHP 5.3–8.5). PDO::query(), PDO::prepare() and PDOStatement::rowCount() exist across that whole range, so the rule behaves the same for every target version. Builtin behavior and argument contracts follow the configured PHP version. Extension-specific calls require resolved extension API symbols; do not treat same-named application functions as extension calls.
Options
None. Enable or disable this rule through normal rule configuration.
Configure
In custos.json:
{
"rules": {
"PdoSelectRowCountAssumption": {
"enabled": true
}
}
}Suppress
Before the statement or declaration (or the first statement of the file):
// @custos-ignore PdoSelectRowCountAssumption